首页 > 其他分享 >Codeforces 794G - Replace All

Codeforces 794G - Replace All

时间:2023-07-21 18:48:26浏览次数:35  
标签:794G lb la int dfrac Codeforces Replace ne 枚举

一个比较垃圾的做法,卡着时限过了这道题。

首先大胆猜个结论:要么 \(|s|=|t|\),此时 \(A,B\) 任取,要么存在字符串 \(c\) 和整数 \(x,y\) 使得 \(A=c^x,B=c^y\),其中 \(c^x\) 表示 \(x\) 个 \(c\) 拼接得到的结果。证明的话感觉还挺复杂的,可能要 border 引理之类的东西,不过我是先写了个暴力发现是 T 了而不是 WA 了才知道自己结论是正确的(

对 \(|s|\) 是否等于 \(|t|\) 分情况讨论:

  • 如果 \(|s|\ne |t|\),先考虑暴力做法:枚举两个字符串中 A 的出现次数,再枚举 \(A,B\) 的长度 \(la,lb\),如果这种情况下 \(s,t\) 总长度相等,那么合法的充要条件是 \(s,t\) 都存在长度为 \(\gcd(la,lb)\) 的周期。考虑优化,假设两串中 A 的出现次数分别为 \(c_1,c_2\),那么两字符串总长相等当且仅当 \(c1·la+(ls-c1)·lb=c2·la+(lt-c2)·lb\)。移项发现 \((c1-c2)(la-lb)=(lt-ls)·lb\)。考虑 \(d=\gcd(la,lb)\),那么你发现一个性质是 \(|\dfrac{la-lb}{d}|\) 必须要是 \(|lt-ls|\) 的因数,这样你考虑枚举 \(d\),枚举 \(\dfrac{lb}{d}\),枚举 \(\dfrac{la-lb}{d}\),然后预处理 \(way_{dif}\) 表示有多少种方法将问号换成 AB 使得 \(c1-c2=dif\)(可以通过组合数求出),然后就可以通过判断是否有 \(\gcd(\dfrac{lb}{d},|\dfrac{la-lb}{d}|)=1\) 来做到快速更新答案。算下枚举量:\(d,\dfrac{lb}{d}\) 的总枚举量是 \(O(n\ln n)\) 的,\(\dfrac{la-lb}{d}\) 的枚举量是 \(d(n)\) 的,所以这部分复杂度 \(O(n\ln n·d(n))\)。

  • 如果 \(|s|=|t|\),那么将贡献分为三部分计算:

    • \(A=B\),方案数 \((\sum\limits_{i=1}^n2^i)·2^{\text{问号个数}}\)
    • \(A\ne B\) 且 \(s\ne t\),那么枚举 \(\gcd(|A|,|B|)=d\),此时必须有 \(s,t\) 中 A 的个数相同,而选择 \(|A|,|B|\) 长度的方案数为 \(\sum\limits_{i=1}^{n/d}\sum\limits_{j=1}^{n/d}[i\perp j][i\ne j]\)。这是经典问题,预处理 \(\varphi(n)\) 的前缀和即可 \(O(1)\) 计算。
    • \(A\ne B\) 且 \(s=t\),\(s=t\) 的方案数可以 \(O(n)\) 算出,设为 \(prd\),那么这部分贡献就是 \(prd·(2^{n+1}-2)·(2^{n+1}-2)-\text{前面被重复计算的贡献}\)。

    这部分时间复杂度 \(O(n)\)。

const int MAXN=3e5;
const int MOD=1e9+7;
int qpow(int x,int e){int ret=1;for(;e;e>>=1,x=1ll*x*x%MOD)if(e&1)ret=1ll*ret*x%MOD;return ret;}
int fac[MAXN*2+5],ifac[MAXN*2+5];
void init_fac(int n){
	for(int i=(fac[0]=ifac[0]=ifac[1]=1)+1;i<=n;i++)ifac[i]=1ll*ifac[MOD%i]*(MOD-MOD/i)%MOD;
	for(int i=1;i<=n;i++)fac[i]=1ll*fac[i-1]*i%MOD,ifac[i]=1ll*ifac[i-1]*ifac[i]%MOD;
}
int pr[MAXN+5],prcnt,vis[MAXN+5],phi[MAXN+5],sphi[MAXN+5];
void sieve(int n){
	phi[1]=1;
	for(int i=2;i<=n;i++){
		if(!vis[i])phi[i]=i-1,pr[++prcnt]=i;
		for(int j=1;j<=prcnt&&pr[j]*i<=n;j++){
			vis[pr[j]*i]=1;
			if(i%pr[j]==0){phi[i*pr[j]]=phi[i]*pr[j];break;}
			else phi[i*pr[j]]=phi[i]*phi[pr[j]];
		}
	}
	for(int i=1;i<=n;i++)sphi[i]=(sphi[i-1]+phi[i])%MOD;
}
int binom(int n,int k){if(n<0||k<0||n<k)return 0;return 1ll*fac[n]*ifac[k]%MOD*ifac[n-k]%MOD;}
char s[MAXN+5],t[MAXN+5];int n,ls,lt,a1,a2,c1,c2,way[MAXN*2+5],pw[MAXN+5],res;
int main(){
	init_fac(MAXN*2);sieve(MAXN);
	scanf("%s%s%d",s+1,t+1,&n);ls=strlen(s+1);lt=strlen(t+1);
	for(int i=1;i<=ls;i++){if(s[i]=='A')++a1;if(s[i]=='?')++c1;}
	for(int i=1;i<=lt;i++){if(t[i]=='A')++a2;if(t[i]=='?')++c2;}
	for(int i=(pw[0]=1);i<=n;i++)pw[i]=pw[i-1]*2%MOD;
	for(int i=-lt;i<=ls;i++)way[i+lt]=binom(c1+c2,i+c2-(a1-a2));
	if(ls==lt){
		int sum=0;for(int i=-lt;i<=ls;i++)if(i!=0)sum=(sum+way[i+lt])%MOD;
		for(int i=1;i<=n;i++)res=(res+1ll*pw[i]*sum)%MOD;
		for(int i=1;i<=n;i++)res=(res+1ll*way[lt]*pw[i]%MOD*(2*sphi[n/i]-1))%MOD;
		int prd=1;
		for(int i=1;i<=ls;i++){
			if(s[i]=='?'&&t[i]=='?')prd=2*prd%MOD;
			else if(s[i]!='?'&&t[i]!='?'&&s[i]!=t[i])prd=0;
		}
		if(prd){
			res=(res+1ll*prd*(2*qpow(2,n)-2)%MOD*(2*qpow(2,n)-2))%MOD;
			for(int i=1;i<=n;i++)res=(res-1ll*prd*pw[i]%MOD*(2*sphi[n/i]-1)%MOD+MOD)%MOD;
		}
	}else{
		vector<int>vec;
		for(int i=1;i<=n;i++)if(abs(lt-ls)%i==0)vec.pb(i),vec.pb(-i);
		static bool ok[505][MAXN+5];
		for(int i=0;i<vec.size();i+=2)for(int B=1;B<=n;B++)
			ok[i][B]=ok[i+1][B]=(__gcd(vec[i],B)==1);
		for(int d=1;d<=n;d++){
			int lim=n/d;
			for(int i=0;i<vec.size();i++){
				int x=vec[i];
				for(int B=max(1-x,1);B<=min(lim,lim-x);B++){
					if(ok[i][B]){
						ll dif=1ll*B*(lt-ls)/x;
						if(-lt<=dif&&dif<=ls)res=(res+1ll*pw[d]*way[dif+lt])%MOD;
					}
				}
			}
		}
	}
	printf("%d\n",res);
	return 0;
}

标签:794G,lb,la,int,dfrac,Codeforces,Replace,ne,枚举
From: https://www.cnblogs.com/tzcwk/p/Codeforces-794G.html

相关文章

  • Codeforces 856F - To Play or not to Play
    首先,DP肯定是逃不掉的,因为直接贪心其实不好判断在两个人都可以上线的时间段究竟是哪个人上线,需要通过后面的情况来做出判断,但是这题值域比较大直接维护DP值肯定不行,因此考虑先设计一个与值域有关的DP然后优化。将时间区间离散化,然后依次考虑每个时间区间。一个很自然的想法......
  • Codeforces Round div.2 C
    Smiling&Weeping----我对姑娘的喜欢,何止钟意二字题目链接:Problem-C-Codeforces自我分析:我感觉这是一道很有意义的题目,可以帮我们更好的理解二进制的本质思路:首先先了解一下题目,我们是求由第i个数到末尾的异或和(异或:相同为0,不同为1),那么我......
  • Codeforces Round 882 div.2 B
    Smiling&Weeping----玫瑰花你拿才好看,风景要和你看才浪漫--<-<-<@B.HamonOdysseytimelimitpertest1secondmemorylimitpertest256megabytesinputstandardinputoutputstandardoutputJonathanisfightingagainstDIO......
  • Codeforces 1696G - Fishingprince Plays With Array Again
    初读题目可以发现一些性质:每次操作会使整个序列的和减少至多\(X+Y\),因此\(ans\ge\dfrac{\suma_i}{X+Y}\)。对于两个不相邻位置\(a_i,a_j(|i-j|>1)\),每次操作最多使它们的和减少\(\max(X,Y)\)。然后你发现两个限制可以结合在一起使用,稍加思考可以得到一个比较普适的结论:......
  • Codeforces 1446F - Line Distance
    感觉这种类似于让你找第\(k\)大距离的计算几何题其实都挺套路的。二分一个答案\(t\),然后思考一下什么样的点对满足原点到它们的连线的距离\(\let\)。以原点为圆心\(t\)为半径画个圆,然后分情况讨论:如果\((x_i,y_i)\)或\((x_j,y_j)\)在圆内,那么必然符合条件。如果\(......
  • Codeforces 1621H - Trains and Airplanes
    这能3500?对于一组在\(u\)上的询问,考虑每种线路\(x\),假设\(1\tou\)路径上线路\(x\)的长度为\(len\),那么不难发现收罚款的次数只有两种可能:\(\lfloor\dfrac{len}{T}\rfloor\)或者\(\lfloor\dfrac{len}{T}\rfloor+1\),且对于一个\(v\)满足\(z_u=z_v\)且\(v\)在\(u......
  • Educational Codeforces Round 151
    AB略C(简)将密码\(P\)与\(S\)进行匹配,按顺序决定\(P_i\),为了避免\(P\)成为\(S\)的子串,每次贪心地选择当前匹配位置最靠后的。若出现匹配不上则“YES”。D有点意思。从基础的情况入手:设\(\{s_i\}\)为\(\{a_i\}\)的前缀和,弄出\(\{s_i\}\)的图像,让我们考虑第一个......
  • Codeforces Round 885 (Div. 2)
    Preface打的就是依托答辩居然也能上分,看来手稳还是重要的说D题半场开香槟以为随便写,然后没想到怎么处理这个局部没有三分性的函数,直接GG后面听学长一说其实分成四种函数分别求最值即可直接恍然大悟,只能说还是太菜太菜而且F好像是个蓝桥杯的某个题的弱化版,我说比赛的时候怎么那......
  • Codeforces Round 882 div.2 A
    Smiling&Weeping----总有人间一两风,填我十万八千梦A.TheManwhobecameaGodtimelimitpertest1secondmemorylimitpertest256megabytesinputstandardinputoutputstandardoutput Kars istiredand......
  • Codeforces Round 885
    目录写在前面ABCDEF写在最后写在前面比赛地址:https://codeforces.com/contest/1848。我现在手里有三套题要补呃呃这套是两天前补的了,所以简单写写。太好玩辣,多校!A考虑一个2x2的矩阵,若小波奇和她的辣妹朋友位于对角线上就会被辣妹朋友堵在墙角,若相邻则永远抓不到。发现移......