链接:牛客网暑期ACM多校训练营(第四场):A Ternary String
题意:给出一段数列 s,只包含 0、1、2 三种数。每秒在每个 2 后面会插入一个 1 ,每个 1 后面会插入一个 0,之后第一个数字消失。求最后为空串需要多少秒。
题解:
(1)如果在消除一个 0 前经过了 n 秒,那么消掉这个 0 需要 n + 1 秒。
(2)如果在消除一个 1 前经过了 n 秒,那么消掉这个 1 与其产生的所有数需要 (n + 1) * 2 秒。
(3)如果在消除一个 2 前经过了 n 秒,那么消掉这个 2 与其产生的所有数需要 (2 ^ (n + 1) - 1) * 3 秒。
需要用欧拉定理降幂。
#include <bits/stdc++.h> using namespace std; const double EPS = 1e-6; const int INF = 0x3f3f3f3f; const long long mod = 1e9 + 7; const int maxn = 1e5 + 10; char s[maxn]; map<long long, long long> mp; long long Eul(long long n) { long long ans = n; for(int i = 2; i * i <= n; i++){ if(n % i == 0){ ans -= ans / i; while(n % i == 0) n /= i; } } if(n > 1) ans -= ans / n; return ans; } long long Mod(long long x, long long y) //欧拉定理的条件 { return x < y ? x : x % y + y; } long long pow_mod(long long x, long long n, long long mod) { long long ans = 1; while(n){ if(n & 1) ans = Mod(ans * x, mod); x = Mod(x * x, mod); n >>= 1; } return ans; } long long DFS(int i, long long mod) { if(i < 0) return 0; long long ans = 0; if(s[i] == '0') return Mod((DFS(i-1, mod) + 1), mod); if(s[i] == '1') return Mod((DFS(i-1, mod) + 1) * 2, mod); if(s[i] == '2') return Mod((pow_mod(2, DFS(i-1, mp[mod]) + 1, mod) - 1) * 3, mod); return ans; } int main() { for(long long x = mod, y = Eul(x); x != y; y = Eul(y)) mp[x] = y, x = y; mp[1] = 1; int T; scanf("%d", &T); while(T--){ scanf("%s", s); printf("%lld\n", DFS(strlen(s) - 1, mod) % mod); } return 0; }