Loading [MathJax]/jax/output/CommonHTML/autoload/mtable.js

NowCoder2018多校A Ternary String 拓展欧拉定理

NowCoder2018多校A Ternary String 拓展欧拉定理

题意

给定带前导0的三进制数,每秒自动进行一次操作,1的后面多一个0,2的后面多一个1,开头的字符被删除,求这个数变为空的操作次数

求操作次数取模1e9+71e9+7

1|s|1051|s|105

分析

考虑记录时间,原串中每个数带来的贡献,可以简单归纳得出

0:t+1t+1

1:2(t+1)2(t+1)

2:3(2t+11)3(2t+11)

操作12都可以轻松得到结果,对于3,计算2t+1 mod MOD2t+1 mod MOD是不方便的,考虑使用拓展欧拉定理

ab{abmodφ(m),gcd(a,m)=1ab,gcd(a,m)1,bφ(m)(mod m)ab modφ(m)+φ(m),gcd(a,m)1,bφ(m)

使用时,要求幂对φ(m)取模,因此我们记录t时还需额外记录φ(m)意义下的t,维护φ(m) 意义下的t又需要嵌套上模φ(φ(m))

为了方便实现,可以采用DFS的方式记录当前第几个数和当前的模数,至于为什么不用判断bφ(m),我也不是很懂

代码

const int MOD = (int)1e9 + 7;

int m[35],ans[35];


inline int mul(int a,int b,int i){
    return (ll)a * b % i;
}


inline  void add(int &a,int b,int i){
    a += b;
    if(a >= i) a -= i;
}

inline int ksm(int a,ll b = MOD - 2,int m = MOD){
    int ans = 1;
    int base = a;
    while(b){
        if(b & 1) {
            ans = (ll)ans * base % m;
        }
        base = (ll)base * base % m;
        b >>= 1;
    }
    return ans;
}


inline int get_phi(int n) {
    int m = int(sqrt(n + 0.5));
    int ans = n;
    for (int i = 2; i <= m; i++) {
        if (n % i == 0) {
            ans = ans / i * (i - 1);
            while (n % i == 0) n /= i;
        }
    }
    if (n > 1) ans = ans / n * (n - 1);
    return ans;
}

unordered_map<int,int> mp;
char s[100005];

int dfs(int len,int m){
    if(!len) return 0;
    if(s[len] == '0')
        return (dfs(len - 1,m) + 1) % m;
    if(s[len] == '1') 
        return (ll)2 * (dfs(len - 1,m) + 1) % m;
    //if(mp[m] != 1) return (mul(3,ksm(2,(dfs(len - 1,mp[m]) + 1) % mp[m],m),m) + m - 3) % m;
    int p = dfs(len - 1,mp[m]) + 1;
    if(m != 1 && m != MOD) {
        if(p >= mp[m]) return (mul(3,ksm(2,p % mp[m] + mp[m],m),m) + m - 3) % m;
        else return (mul(3,ksm(2,p % mp[m],m),m) + m - 3) % m;
    }  
    return (mul(3,ksm(2,p % mp[m],m),m) + m - 3) % m;
}

int main(){
    int T = rd();
    int tmp = MOD;
    mp[1] = 1;
    while(tmp > 1) {
        mp[tmp] = get_phi(tmp);
        tmp = mp[tmp];
    }
    while(T--){
       scanf("%s",s + 1);
       int len = strlen(s + 1);
       printf("%d\n",dfs(len,MOD));
    }
}
posted @   MQFLLY  阅读(37)  评论(0编辑  收藏  举报
编辑推荐:
· 深入理解 Mybatis 分库分表执行原理
· 如何打造一个高并发系统?
· .NET Core GC压缩(compact_phase)底层原理浅谈
· 现代计算机视觉入门之:什么是图片特征编码
· .NET 9 new features-C#13新的锁类型和语义
阅读排行:
· Sdcb Chats 技术博客:数据库 ID 选型的曲折之路 - 从 Guid 到自增 ID,再到
· 语音处理 开源项目 EchoSharp
· 《HelloGitHub》第 106 期
· Spring AI + Ollama 实现 deepseek-r1 的API服务和调用
· 使用 Dify + LLM 构建精确任务处理应用
历史上的今天:
2020-10-05 线段树模板2.0
点击右上角即可分享
微信分享提示
主题色彩