牛客网暑期ACM多校训练营(第四场):A Ternary String(欧拉降幂)

链接:牛客网暑期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;
}

猜你喜欢

转载自www.cnblogs.com/chenquanwei/p/9383282.html