题意:问多长时间后可以将整个序列完全消除,每秒序列会在
1
1
后面插入一个,在
2
2
后面插入一个,作为序列的第一个数字将会消失。最后答案对
1e9+7
1
e
9
+
7
取模。
emmm,通过打表就可以发现
假设现有一个长度为
n
n
的序列,
每次序列插入一个后,我们需要
n+1
n
+
1
秒才能将这个序列消除;
每次序列插入一个
1
1
后,我们需要秒才能将这个序列消除;
每次序列插入一个
2
2
后,我们需要秒才能将这个序列消除。
再来看一下数据范围, n n 最大有,明显在处理 3⋅(2n+1−1) 3 ⋅ ( 2 n + 1 − 1 ) 的时候会超时。所以此时欧拉降幂就能很好的优化这种算式了。详情请看蒻刚补的叭。然后如果泥萌看了我的那篇欧拉定理的话,就会发现如果我们从 φ(1e9+7) φ ( 1 e 9 + 7 ) 不断嵌套求 φ φ 值,每次模数除了第一次都是偶数,最后我们一定可以在不多于 log2(p) l o g 2 ( p ) 次内将 φ φ 值降为 1 1 ,所以可以采用递归回溯计算。
。
但是这里为了方便理解,窝就贴一个非递归的代码。。因为是多组数据,因此我们需要预处理出 φ(φ(φ(...φ(1e9+7)))) φ ( φ ( φ ( . . . φ ( 1 e 9 + 7 ) ) ) ) 。
#include<bits/stdc++.h>
typedef long long LL;
LL phi(LL n) {
LL ret = 1;
for (LL i = 2; i * i <= n; ++i) {
if (n % i == 0) {
n /= i, ret *= i - 1;
while (n % i == 0)
n /= i, ret *= i;
}
}
if (n > 1) ret *= n - 1;
return ret;
}
std::map<LL,LL> m;
char s[100001];
LL pow_(LL a,LL n,LL mod) {
LL ans = 1;
while (n) {
if (n & 1) ans = ans * a % mod;
a = a * a % mod;
n >>= 1;
}
return ans;
}
int main() {
LL T;
m[0] = 1e9 + 7;
for (int i = 1; i < 1e5; ++i)
m[i] = phi(m[i - 1]);
std::cin >> T;
while (T--) {
std::cin >> s;
int cnt = 0;
for (int i = 0; s[i]; ++i)
if (s[i] == '2')
cnt++;
LL ans = 0;
for (int i = 0; s[i]; ++i) {
if (s[i] == '0')
ans++, ans %= m[cnt];
else if (s[i] == '1')
ans = (ans * 2 + 2) % m[cnt];
else {
cnt--;
if (ans < m[cnt])
ans = 3 * (pow_(2, (ans + 1) % m[cnt], m[cnt]) - 1 + m[cnt]) % m[cnt];
else
ans = 3 * (pow_(2, (ans + 1) % m[cnt] + m[cnt], m[cnt]) - 1 + m[cnt]) % m[cnt];
}
}
std::cout << ans << std::endl;
}
return 0;
}
因篇幅问题不能全部显示,请点此查看更多更全内容