A. Ternary String 牛客网暑期ACM多校训练营(第四场)

 A. Ternary String  牛客网暑期ACM多校训练营(第四场)

题目链接

A ternary string is a sequence of digits, where each digit is either 0, 1, or 2.
Chiaki has a ternary string s which can self-reproduce. Every second, a digit 0 is inserted after every 1 in the
string, and then a digit 1 is inserted after every 2 in the string, and finally the first character will disappear.
For example, ``212'' will become ``11021'' after one second, and become ``01002110'' after another
second.
Chiaki would like to know the number of seconds needed until the string become an empty string. As the
answer could be very large, she only needs the answer modulo (109 + 7).
输入描述:
There are multiple test cases. The first line of input is an integer T indicates the number of test cases. For
each test case:
The first line contains a ternary string s (1 ≤ |s| ≤ 10 5).
It is guaranteed that the sum of all |s| does not exceed 2 x 10 6.
输出描述:
For each test case, output an integer denoting the answer. If the string never becomes empty, output -1
instead.

题意:给你一个字符串,由0,1,2组成,每秒钟在1后面添加一个0,在二后面添加一个1,然后去掉字符串的首个字符,问需要多少秒后,字符串变成空串。

思路:由于2会生成1并且总会被移到字符串的队首消去,1会生成0并且总会被移到字符串的队首消去,0不会生成其他数字并且总会被移到字符串的队首消去,所以总会有答案,使得在ans秒后字符串变成空串。我们暴力模拟一波,发现222的时候就直接爆炸了......我们假设当t秒后,字符a移动到字符串的队首,那么将字符a去掉后,会消耗多少时间呢?我们先打一波表,打出

10
1
01
001
0001
00001
000001
0000001
00000001
000000001
0000000001

的答案是2,4,6,8,10,12,14,16,18,20

10
2
02
002
0002
00002
000002
0000002
00000002
000000002
0000000002

的答案是3,9,21,45,93,189,381,765,1533,3069

我们可以推出当a=0时,f(t)=t+1;当a=1时,f(t)=2*(t+1);当a=2时,f(t)=3*(2^(t+1)-1);其中f(t)表示当前的a被消掉的时候消耗的时间。比赛的时候不会预处理欧拉降幂,一直卡50%的测试样例,这道题就当做学习欧拉降幂吧。

由于要处理3*(2^(t+1)-1)的式子,当t非常大的时候,对t直接取模后,再跑快速幂下,跑出来的是错误的。需要对t进行欧拉降幂。由于每一次计算需要的是降幂后的phi(mod),phi(phi(mod)),phi(phi(phi(mod))).....可以先预处理出所有的欧拉降幂的结果,在从结果开始往前开始进行dfs即可得出答案。

#include<bits/stdc++.h>
#define lson l,m
#define rson m+1,r
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn = int(1e5) + 100;
const int maxm=100;
const int BN = 30;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const int mod = (int)1e9 + 7;
const double EPS = 1e-12;
char str[maxn];
map<ll,ll>mo;
ll phi(ll x) {   //欧拉降幂 
	ll res=x,a=x;
	for(ll i=2; i*i<=x; i++) {
		if(a%i==0) {
			res=res/i*(i-1);
			while(a%i==0) a/=i;
		}
	}
	if(a>1) res=res/a*(a-1);
	return res;
}
ll quick_pow(ll base,ll n,ll modd) {  //快速幂 
	ll ans=1;
	while(n) {
		if(n&1) ans=ans*base%modd;
		base=base*base%modd;
		n>>=1;
	}
	return ans;
}
void init(int mod){   //预处理出所有的欧拉降幂 
	while(mod!=1){
		mo[mod]=phi(mod);
		mod=mo[mod];
	}
	mo[1]=1;
}
ll dfs(int pos,int mod) {
	if(pos==0) return 0;
	else if(str[pos]=='0') return (dfs(pos-1,mod)+1)%mod;
	else if(str[pos]=='1') return (2*dfs(pos-1,mod)+2)%mod;
	else return (3*quick_pow(2,dfs(pos-1,mo[mod])+1,mod)-3+mod)%mod;
}
int main() {
	init(mod);
	int T;
	scanf("%d",&T);
	while(T--) {
		memset(str,0,sizeof(str));
		scanf("%s",str+1);
		int len=strlen(str+1);
		ll ans=dfs(len,mod);
		printf("%lld\n",ans);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_40160605/article/details/81267216