原文链接https://www.cnblogs.com/zhouzhendong/p/NowCoder-2018-Summer-Round4-A.html

题目传送门 - https://www.nowcoder.com/acm/contest/142/A

题意

  给定一个长度为 $n$ ,只包含 $0,1,2$ 的数列。

  每一秒会依次进行如下操作:

  1. 所有的 $1$ 后面生出一个 $0$

  2. 所有的 $2$ 后面生出一个 $1$

  3. 第一个数字消失了

  问经过多少时间之后,数列全部消失。

  多组数据。

  答案对于 $10^9+7$ 取模。 $n\leq 10^5,\sum n\leq 2\times 10^6$

题解

  假设当前时间为 $t$ ,我们可以简单推一波式子分别得到消灭下一个数字及其生出来的数字之后的时间:

  如果下一个数字是   :则

          0 : $t^\prime=t+1$

          1 : $t^\prime=2t+2$

          2 : $t^\prime=6\times 2^t-3$

  那么由于 $t$ 会出现在指数上面,我们不能随意将 $t$ 对 $10^9+7$ 取模。

  我当场写了个 $O(n\log n)$ 的,一个有点低级的错误续了我很久(看来昨天念诗之后还有后遗症啊)

  考虑欧拉定理:

  当 $\gcd(a,b)=1$ 时,$a^{\phi (b)}\equiv 1 \pmod b$ 。

  由于这里 $a=2$ ,所以我们可以进行推广。

  记 $b=x\times 2^y,a=2^{k+y}$ ,则当 $k\geq 0$ 时 :

$$2^{k+y}\equiv 2^{(k \mod {\phi(x)}) + y}\pmod {x\times 2^y}$$

  于是我们可以使 $k$ 取模。

  但是如果 $k<0$ 呢,那么显然这个数字很小,直接算出来。

  注意一下 $y$ 的值也是很小的。

  我们处理一下前面较小的一部分的答案,然后从后往前根据上式递归求解即可。

  时间复杂度 $O(n\log n)$ 。

代码

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=100005;
int T,ps[N],x[N],y[N],px[N],pt[N];
char s[N];
int Pow(int x,int y,int mod){
int ans=1;
for (;y;y>>=1,x=1LL*x*x%mod)
if (y&1)
ans=1LL*ans*x%mod;
return ans;
}
int phi(int x){
int ans=x;
for (int i=2;i*i<=x;i++){
if (x%i==0){
ans=ans/i*(i-1);
while (x%i==0)
x/=i;
}
}
if (x>1)
ans=ans/x*(x-1);
return ans;
}
int solve(int j,int k){
if (j==0||pt[j]>0)
return pt[j];
int i=j;
while (i>0&&s[i]!='2')
i--;
int t=i==0?0:((6LL*Pow(2,solve(i-1,k+1),x[k])-3)%x[k]);
for (int p=i+1;p<=j;p++){
if (s[p]=='0')
t=(t+1)%x[k];
if (s[p]=='1')
t=(2*t+2)%x[k];
}
t=((t-y[k])%x[k]+x[k])%x[k];
return t+y[k];
}
int main(){
ps[0]=1e9+7;
for (int i=1;i<=100000;i++)
ps[i]=phi(ps[i-1]);
for (int i=1;i<=100000;i++){
for (x[i]=ps[i-1],y[i]=0;x[i]%2==0;x[i]>>=1,y[i]++);
x[i]=phi(x[i]);
}
x[0]=ps[0],y[0]=0;
scanf("%d",&T);
while (T--){
scanf("%s",s+1);
int n=strlen(s+1),i=0;
for (int x=0;i<n;i++,pt[i]=x){
if (s[i+1]=='0')
x++;
if (s[i+1]=='1')
x=x*2+2;
if (s[i+1]=='2')
x=6*Pow(2,x,1e9+7)-3;
if (x>=21)
break;
}
printf("%d\n",(solve(n,0))%ps[0]);
for (;i>0;i--)
pt[i]=0;
}
return 0;
}

  

2018牛客网暑假ACM多校训练赛(第四场)A Ternary String 数论的更多相关文章

  1. 2018牛客网暑假ACM多校训练赛(第二场)E tree 动态规划

    原文链接https://www.cnblogs.com/zhouzhendong/p/NowCoder-2018-Summer-Round2-E.html 题目传送门 - 2018牛客多校赛第二场 E ...

  2. 2018牛客网暑假ACM多校训练赛(第三场)I Expected Size of Random Convex Hull 计算几何,凸包,其他

    原文链接https://www.cnblogs.com/zhouzhendong/p/NowCoder-2018-Summer-Round3-I.html 题目传送门 - 2018牛客多校赛第三场 I ...

  3. 2018牛客网暑假ACM多校训练赛(第三场)G Coloring Tree 计数,bfs

    原文链接https://www.cnblogs.com/zhouzhendong/p/NowCoder-2018-Summer-Round3-G.html 题目传送门 - 2018牛客多校赛第三场 G ...

  4. 2018牛客网暑假ACM多校训练赛(第三场)D Encrypted String Matching 多项式 FFT

    原文链接https://www.cnblogs.com/zhouzhendong/p/NowCoder-2018-Summer-Round3-D.html 题目传送门 - 2018牛客多校赛第三场 D ...

  5. 2018牛客网暑假ACM多校训练赛(第十场)H Rikka with Ants 类欧几里德算法

    原文链接https://www.cnblogs.com/zhouzhendong/p/NowCoder-2018-Summer-Round10-H.html 题目传送门 - https://www.n ...

  6. 2018牛客网暑假ACM多校训练赛(第十场)F Rikka with Line Graph 最短路 Floyd

    原文链接https://www.cnblogs.com/zhouzhendong/p/NowCoder-2018-Summer-Round10-F.html 题目传送门 - https://www.n ...

  7. 2018牛客网暑假ACM多校训练赛(第十场)D Rikka with Prefix Sum 组合数学

    原文链接https://www.cnblogs.com/zhouzhendong/p/NowCoder-2018-Summer-Round10-D.html 题目传送门 - https://www.n ...

  8. 2018牛客网暑假ACM多校训练赛(第八场)H Playing games 博弈 FWT

    原文链接https://www.cnblogs.com/zhouzhendong/p/NowCoder-2018-Summer-Round8-H.html 题目传送门 - https://www.no ...

  9. 2018牛客网暑假ACM多校训练赛(第七场)I Tree Subset Diameter 动态规划 长链剖分 线段树

    原文链接https://www.cnblogs.com/zhouzhendong/p/NowCoder-2018-Summer-Round7-I.html 题目传送门 -  https://www.n ...

  10. 2018牛客网暑假ACM多校训练赛(第六场)I Team Rocket 线段树

    原文链接https://www.cnblogs.com/zhouzhendong/p/NowCoder-2018-Summer-Round6-I.html 题目传送门 - https://www.no ...

随机推荐

  1. python pip下载速度慢的解决方法

    pip是python内置的非常好用的下载工具,基本可以下载全部的python库.它还有一个非常好的特点,当你安装一个库的时候,它会自动帮你安装所有这个库的依赖库.完全一键式操作.非常方便.但是由于pi ...

  2. /var/run/yum.pid 已被锁定,PID 为 2925 的另一个程序正在运行

    解决办法:直接在终端运行 rm -f /var/run/yum.pid 将该文件删除,然后再次运行yum.

  3. Android中验证输入是否为汉字、手机号及邮箱

    1,验证是否为汉字 Code// 验证昵称 private boolean verifyNickname() { String nickname = edt_username.getText().to ...

  4. Winform按键捕获

    参考:http://blog.csdn.net/zhensoft163/article/details/4239796 下载链接 方法1:使用窗体的 KeyDown 事件 private void F ...

  5. Eclipse中三种设置编码格式的方法

    转自:https://blog.csdn.net/rainy_black_dog/article/details/52403735 很早以前听过一位老师说过:咱们中国人不管学习哪种编程语言,总会遇到乱 ...

  6. Ex 2_23 如果一个数组超过半数的元素都相同时,该数组被称为含有一个主元素..._第二次作业

    将数组A划分为两个数组A1和A2 ,各含有A的一半元素或一半多一个.若A中含有主元素x,则A1和A2中至少有一个数组含有主元素x,对A1和A2递归地计算有无主元素,若A只含有一个元素,则A的主元素就是 ...

  7. python元组,集合类型,及字典补充

    一.元组 元组与列表基本相同,不同之处在于元组只能存不能取,当多个值没有改的需求时,用元组更合适 元组的基本操作 1.创建元组: t = (1, 2, 3, 4, 2,4,) t = (1,) #单个 ...

  8. MySQL笔记二

    Ø function 函数 函数的作用比较大,一般多用在select查询语句和where条件语句之后.按照函数返回的结果, 可以分为:多行函数和单行函数:所谓的单行函数就是将每条数据进行独立的计算,然 ...

  9. 经典JS闭包面试题(来理解闭包)(转)

    转载地址:http://www.cnblogs.com/xxcanghai/p/4991870.html 先看代码: function fun(n,o) { console.log(o) return ...

  10. Ubuntu16.04安装MySQL

      本篇教程在示例步骤中使用了以下版本的软件.操作时,请您以实际软件版本为准. 操作系统:Ubuntu 16.04.3 LTS (GNU/Linux 4.4.0-105-generic x86_64) ...