ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#470 | #92. 「NOIP2020」微信步数 | Pigsyy | 100 | 334ms | 10220kb | C++23 | 7.0kb | 2025-04-24 20:47:51 | 2025-04-24 20:47:53 |
answer
#include <bits/stdc++.h>
using namespace std;
bool Mbegin;
void File_Work() {
freopen("walk.in", "r", stdin);
freopen("walk.out", "w", stdout);
}
namespace Fast_In_Out {
char buf[1 << 21], *P1 = buf, *P2 = buf;
#define gc (P1==P2&&(P2=(P1=buf)+fread(buf,1,1<<21,stdin),P1==P2)?EOF:*P1++)
int read() {
int f = 1, x = 0;
char c = gc;
while (c < '0' || c > '9') {
if (c == '-')
f = -1;
c = gc;
}
while (c >= '0' && c <= '9') {
x = x * 10 + c - '0';
c = gc;
}
return f * x;
}
void write(int x) {
if (x < 0)
x = -x, putchar('-');
if (x > 9)
write(x / 10);
putchar(x % 10 + '0');
}
#undef gc
}
using namespace Fast_In_Out;
/*
注意到走出场地的时刻,就是某一维的坐标范围第一次超出对应的限制范围的时刻。
所以只需要关心每一维坐标的最大值、最小值。
考虑将起点分成两类:走不超过n步就能出去的、走超过n步才能出去的。
对于第一类起点,枚举i表示走i步恰好走出去,
方案数为前i-1步对应的坐标范围在限制范围内的方案数,
减去前i步对应的坐标范围在限制范围内的方案数。
对于两者,合法的起点都在一个高维矩形里,可以乘法计算方案数。
对于第二类起点,考虑将答案拆成最后一轮走的步数和之前走的步数之和(是n的倍数)。
先考虑前者。
枚举一个“假起点”,满足真正的起点走整数轮之后到达“假起点”,
再走n+i步走出场地(1小于等于i小于等于n)。
记一轮之后第i维坐标的增量维dt[i],方便起见,dt[i]≥0且不全为0。
设真起点维(a[1],a[2],…,a[m]),假起点为(b[1],b[2],…,b[m])。
则a[i]=b[i]-y*dt[i](y≥0)。
考虑先固定假起点,则真起点还要满足形如a[i]≥l[i]的若干条限制。
所以真起点的个数为floor(min((b[i]-l[i])/dt[i]))+1。
考虑假起点的坐标范围也是一个高维矩形,可以二维差分算贡献。
同时,假起点的坐标范围满足形如l[i]≤b[i]<r[i]的限制。
设p[i]=r[i]-l[i],方案数为:
Σ(l[1]≤i[1]≤r[1]-1)…Σ(l[m]≤i[m]≤r[m]-1)(floor(min((b[i]-l[i])/dt[i]))+1)
=Σ(0≤j[1]≤p[1]-1)…Σ(0≤j[m]≤p[m]-1)(floor(min(j[i]/dt[i]))+1)
=Σ(q≥0)Σ(0≤j[1]≤p[1]-1)…Σ(0≤j[m]≤p[m]-1)[floor(min(j[i]/dt[i]))≥q]
=Σ(q≥0)∏(1≤i≤m)(max(0,p[i]-q*dt[i]))
注意到q大于等于一个数lim时后面的乘积就会是0,所以可以去掉max。
将式子看作关于q的多项式,方案数为:
Σ(0≤q≤lim-1)∏(1≤i≤m)(p[i]-q*dt[i])
=Σ(0≤q≤lim-1)Σ(0≤i≤m)(f[i]*(q^i))
=(Σ(0≤q≤lim-1)f[i])*(Σ(0≤i≤m)(q^i))
前面的系数容易计算,后面的自然数幂和可以O(m^2)计算。
考虑后者。
枚举y表示走y整轮还没走出边界,然后给答案加上(n×合法起点数)。
发现合法的起点还是高维矩形,且y每增加1,高维矩形第i维的长度就会少dt[i]。
因此前者和后者本质相同。
需要预处理逆元和第二类斯特林数,总复杂度O(nm^2)。
*/
const int N = 5e5 + 8, M = 18, mod = 1e9 + 7;
int n, m, w[M], c[N], d[N], dt[N];
int inv[M + 1], S[M + 1][M + 1]/*第二类斯特林数*/;
void prepare() {
S[0][0] = 1;
for (int i = 1; i <= M; i++)
for (int j = 1; j <= i; j++)
S[i][j] = (+S[i - 1][j - 1] + 1ll * j * S[i - 1][j] % mod) % mod;
inv[0] = inv[1] = 1;
for (int i = 2; i <= M; i++)
inv[i] = 1ll * (mod - mod / i) * inv[mod % i] % mod;
}
struct Space {
int l[M], r[M], dtx[M];
Space() {
memset(l, 0, sizeof(l));
memset(r, 0, sizeof(r));
memset(dtx, 0, sizeof(dtx));
}
int walk(int c, int d) {
dtx[c] += d;
if (dtx[c] < l[c] || dtx[c] > r[c]) {
l[c] = min(l[c], dtx[c]);
r[c] = max(r[c], dtx[c]);
return d;
}
return 0;
}
} spc/*描述各维的坐标区间和位移*/, spc0/*一开始的spc*/;
int calc(int idx, int lim) {
int tmp = 1, res = 0;
for (int i = 0; i <= idx; i++) {
tmp = 1ll * tmp * max(0, lim - i) % mod;
res = (res + 1ll * tmp * S[idx][i] % mod * inv[i + 1] % mod) % mod;
}
return res;
}
int work(int *arr) {
int lim = mod;
for (int i = 0; i < m; i++)
if (dt[i] != 0)
lim = min(lim, (arr[i] + dt[i] - 1) / dt[i]);
int f[M] = {0};
f[0] = 1;
for (int i = 0; i < m; i++) {
for (int j = i; j >= 0; j--) {
f[j + 1] = (f[j + 1] + 1ll * (mod - dt[i]) * f[j] % mod) % mod;
f[j] = 1ll * arr[i] * f[j] % mod;
}
}
int res = 0;
for (int i = 0; i <= m; i++)
res = (res + 1ll * f[i] * calc(i, lim) % mod) % mod;
return res;
}
bool Mend;
int main() {
prepare();
n = read(), m = read();
for (int i = 0; i < m; i++)
w[i] = read();
int ans = 0;
for (int i = 1; i <= n; i++) {
c[i] = read() - 1, d[i] = read();
if (spc.walk(c[i], d[i]) != 0 && spc.r[c[i]] - spc.l[c[i]] <= w[c[i]]) {
int tmp = 1;
for (int j = 0; j < m; j++)
if (j != c[i])
tmp = 1ll * tmp * max(0, w[j] - (spc.r[j] - spc.l[j])) % mod;
ans = (+ans + 1ll * i * tmp % mod) % mod;
}
}
for (int i = 1; i <= n; i++)
if (spc.dtx[c[i]] < 0)
d[i] = -d[i];
for (int i = 0; i < m; i++) {
if (spc.dtx[i] < 0) {
spc.dtx[i] = -spc.dtx[i];
spc.l[i] = -spc.l[i];
spc.r[i] = -spc.r[i];
swap(spc.l[i], spc.r[i]);
}
}
spc0 = spc;
bool flag = 1;
for (int i = 0; i < m; i++) {
dt[i] = spc.dtx[i];
flag &= dt[i] == 0;
}
if (flag == 1) {
bool ok = 0;
for (int i = 0; i < m; i++)
ok |= (spc.r[i] - spc.l[i] >= w[i]);
if (ok == 0)
printf("-1");
else
write(ans);
return 0;
}
int arr[M] = {0};
for (int i = 1; i <= n; i++) {
if (spc.walk(c[i], d[i]) != 0 && spc.r[c[i]] - spc.l[c[i]] <= w[c[i]]) {
bool ok = 1;
for (int j = 0; j < m; j++)
if (j != c[i])
ok &= (w[j] - (spc.r[j] - spc.l[j]) > 0);
if (ok == 0)
continue;
for (int j = 0; j < m; j++)
if (j != c[i])
arr[j] = w[j] - (spc.r[j] - spc.l[j]);
arr[c[i]] = w[c[i]] - (spc.r[c[i]] - spc.l[c[i]] - 1);
ans = (ans + 1ll * i * work(arr) % mod) % mod;
arr[c[i]] = w[c[i]] - (spc.r[c[i]] - spc.l[c[i]]);
ans = (ans + 1ll * (mod - i) * work(arr) % mod) % mod;
}
}
for (int i = 0; i < m; i++)
arr[i] = max(0, w[i] - (spc0.r[i] - spc0.l[i]));
ans = (ans + 1ll * n * work(arr) % mod) % mod;
write(ans);
return 0;
}
Details
小提示:点击横条可展开更详细的信息
Test #1:
score: 5
Accepted
time: 2ms
memory: 9380kb
input:
5 5 2 2 1 3 3 1 1 2 -1 1 1 5 -1 5 1
output:
63
result:
ok "63"
Test #2:
score: 5
Accepted
time: 3ms
memory: 9432kb
input:
5 5 2 2 2 3 2 5 -1 5 1 2 1 2 1 5 1
output:
108
result:
ok "108"
Test #3:
score: 5
Accepted
time: 0ms
memory: 9440kb
input:
5 5 3 3 1 3 2 4 1 4 -1 1 -1 3 -1 2 1
output:
150
result:
ok "150"
Test #4:
score: 5
Accepted
time: 0ms
memory: 9680kb
input:
100 3 8 7 6 1 1 1 -1 3 1 3 -1 3 1 3 -1 3 1 3 -1 1 1 1 -1 1 1 1 -1 2 1 2 -1 1 1 1 -1 2 1 2 -1 3 1 3 -...
output:
-1
result:
ok "-1"
Test #5:
score: 5
Accepted
time: 1ms
memory: 9496kb
input:
100 3 6 7 5 1 1 2 1 3 1 2 -1 2 -1 3 -1 3 -1 2 -1 3 1 2 -1 2 -1 2 1 1 -1 1 1 2 -1 2 -1 2 1 3 -1 3 -1 ...
output:
1445
result:
ok "1445"
Test #6:
score: 5
Accepted
time: 0ms
memory: 7396kb
input:
100 3 5 7 6 3 1 1 1 2 -1 2 -1 2 1 2 1 1 1 1 -1 2 1 2 -1 3 1 2 1 3 -1 2 -1 1 1 1 -1 1 -1 3 1 2 1 1 1 ...
output:
1823
result:
ok "1823"
Test #7:
score: 5
Accepted
time: 7ms
memory: 7648kb
input:
100000 1 84020 1 -1 1 -1 1 1 1 -1 1 1 1 1 1 -1 1 -1 1 1 1 -1 1 -1 1 1 1 1 1 -1 1 1 1 -1 1 1 1 1 1 1 ...
output:
333173136
result:
ok "333173136"
Test #8:
score: 5
Accepted
time: 8ms
memory: 9416kb
input:
100000 1 74078 1 -1 1 1 1 1 1 -1 1 -1 1 -1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 -1 1 -1 1 -1 1 -1 1 1 ...
output:
453472675
result:
ok "453472675"
Test #9:
score: 5
Accepted
time: 5ms
memory: 9388kb
input:
100000 2 788727 548098 1 -1 2 1 2 -1 2 1 1 -1 1 1 2 -1 2 -1 1 -1 2 1 2 -1 2 1 2 -1 1 -1 2 -1 2 1 1 -...
output:
433871022
result:
ok "433871022"
Test #10:
score: 5
Accepted
time: 12ms
memory: 9572kb
input:
100000 2 851838 526074 1 1 1 1 1 1 1 -1 2 -1 2 -1 1 1 2 1 2 1 2 1 2 1 1 1 1 -1 2 1 1 1 2 1 1 -1 2 -1...
output:
635878930
result:
ok "635878930"
Test #11:
score: 5
Accepted
time: 7ms
memory: 9436kb
input:
100000 2 936902 869936 1 -1 1 -1 1 -1 2 -1 2 1 1 -1 2 1 2 1 2 -1 1 1 2 -1 2 -1 1 -1 2 -1 1 -1 1 -1 1...
output:
442317474
result:
ok "442317474"
Test #12:
score: 5
Accepted
time: 5ms
memory: 9416kb
input:
100000 2 696105 696736 2 1 1 -1 1 -1 1 1 1 1 1 -1 1 -1 2 1 2 -1 2 -1 1 -1 1 1 1 -1 2 1 2 -1 1 1 2 -1...
output:
564885404
result:
ok "564885404"
Test #13:
score: 5
Accepted
time: 14ms
memory: 9996kb
input:
500000 10 755576 503368 607237 931815 889701 742191 594456 676526 704905 569952 9 1 9 -1 8 1 8 -1 4 ...
output:
-1
result:
ok "-1"
Test #14:
score: 5
Accepted
time: 39ms
memory: 9744kb
input:
500000 10 843479 559917 806296 766435 965493 781368 889933 632099 689781 934269 3 1 10 1 3 1 3 -1 6 ...
output:
212475448
result:
ok "212475448"
Test #15:
score: 5
Accepted
time: 47ms
memory: 9560kb
input:
500000 10 564550 662731 907937 653446 887637 552698 501487 502890 574491 689451 8 -1 2 1 2 -1 10 -1 ...
output:
27023740
result:
ok "27023740"
Test #16:
score: 5
Accepted
time: 52ms
memory: 9200kb
input:
500000 10 918488 957499 964399 900665 976079 674192 501308 980114 958902 545155 6 1 1 -1 1 1 9 1 1 1...
output:
128050940
result:
ok "128050940"
Test #17:
score: 5
Accepted
time: 31ms
memory: 10220kb
input:
500000 3 826619243 796070724 841056572 3 1 2 1 3 -1 1 -1 2 1 2 -1 1 -1 1 1 1 -1 3 1 1 -1 2 -1 3 -1 3...
output:
953829771
result:
ok "953829771"
Test #18:
score: 5
Accepted
time: 34ms
memory: 9324kb
input:
500000 3 956491428 866109891 631435277 2 1 1 -1 1 -1 3 -1 3 1 2 -1 2 1 1 -1 2 1 2 -1 1 -1 2 1 2 1 2 ...
output:
286394049
result:
ok "286394049"
Test #19:
score: 5
Accepted
time: 31ms
memory: 9952kb
input:
500000 3 816766322 779617142 794227651 3 1 2 1 1 1 3 -1 2 1 2 -1 1 1 1 1 1 1 3 -1 1 -1 2 1 3 1 1 -1 ...
output:
950925221
result:
ok "950925221"
Test #20:
score: 5
Accepted
time: 36ms
memory: 10072kb
input:
500000 3 600925621 781710332 540983402 1 -1 1 1 2 1 3 1 1 1 1 1 3 1 3 1 2 -1 3 -1 3 1 1 -1 1 1 2 -1 ...
output:
370329204
result:
ok "370329204"