CodeForces 794 G.Replace All

解题思路

首先如果字符串 \(A, B\) 没有匹配,那么二元组 \((S, T)\) 合法的一个必要条件是存在正整数对 \((x,y)\),使得 \(xS=yT\),其中 \(xS\) 是将字符串 \(S\) 复制 \(x\) 遍后得到的字符串,\(yT\) 是将字符串 \(T\) 复制 \(T\) 遍后得到的字符串。由于 \(A,B\) 直接匹配的情况比较容易讨论,下面没有特殊说明,都是 \(A,B\) 没有直接匹配的情况。

这个条件的实际意义是通过这个二元组 \((S,T)\) 转化后,能将 \(x\) 个 \('a'\) 组成的子串与 \(y\) 个 \('b'\) 组成的子串通配,必要性可以根据这个感性理解,下面来证明满足这个条件的二元组的一些性质。

对于字符串 \(C=xS=yT\) ,显然存在周期 \(x\) 和周期 \(y\) ,根据周期定理 \(\gcd(x,y)\) 也是 \(C\) 的一个周期,其也是 \(S,T\) 的一个周期,我们令 \(C[1:\gcd(x,y)]=D\) ,那么 \(S=\dfrac{y}{\gcd(x,y)}D,T=\dfrac{x}{\gcd(x,y)}D\) 。用 \(+\) 表示字符串的拼接,可以得到 \(S+T=T+S=\dfrac{xy}{\gcd(x,y)}D\) 。也就是用这个二元组转化后,任意两个相邻的字符 \('a','b'\) 交换后得到的字符串不变,最终的字符串只与字符 \('a','b'\) 的数量用关。

假设将 \('?'\) 填好之后,令 \(\Delta a\) 表示 \(A\) 中 \('a'\) 的数量与 \(B\) 中 \('a'\) 的数量之差,\(\Delta b\) 表示 \(A\) 中 \('b'\) 的数量与 \(B\) 中 \('b'\) 的数量之差,此时如果 \(\Delta a \Delta b\geq0\) 且 \(\Delta a,\Delta b\) 不同时等于 \(0\) ,那么不存在满足条件的合法二元组。

如果 \(\Delta a=0,\Delta b=0\) ,那么任意一个满足条件的合法二元组都可以,其中一个 \(\gcd(x,y)=g\) 的合法二元组的方案数就是 \(2^g\) (考虑字符串 \(D\) 的每一位是怎么填的即可),那么只需要容斥出所有 \(\gcd(x,y)=i\) 的对数即可。

否则,满足条件的 \(x, y\) 的比值是 \(\dfrac{|\Delta a|}{|\Delta b|}\) ,令 \(g=\gcd(\Delta a,\Delta b)\) ,枚举 \(D\) 的长度,方案数就是

\[2^{\dfrac{n}{\dfrac{\max(|\Delta a|,|\Delta b|)}{g}}+1}-2
\]

现在考虑 \('?'\) 的影响,令 \(cntA\) 为 \(A\) 中 \('?'\) 个数,\(cntB\) 为 \(B\) 中 \('?'\) 个数,那么填 \('?'\) 的影响就是让 \(\Delta a\) 加上一个整数 \(d\),\(\Delta b\) 加上 \(cntA-cntB-d\),这样选的方案数是 \({cntA+cntB}\choose{cntB+d}\) ,推导可以把方案数的和式列出来然后展开,当然你要做卷积也是可以的。(模数 \(10^9+7\)) ,然后只需要枚举一下 \('?'\) 贡献的 \(d\) 的值这一部分就算出来了。

注意前面提到的都是 \(A,B\) 没有直接匹配的情况,对于 \(A,B\) 在填完 \('?'\) 之后能直接匹配的情况,所有的二元组都是合法的,只需要把之前没算的部分在这里算上即可,总的复杂度是 \(\mathcal O(n\log n)\) 。

code

/*program by mangoyang*/
#include <bits/stdc++.h>
#define inf (0x7f7f7f7f)
#define Max(a, b) ((a) > (b) ? (a) : (b))
#define Min(a, b) ((a) < (b) ? (a) : (b))
typedef long long ll;
using namespace std;
template <class T>
inline void read(T &x){
int ch = 0, f = 0; x = 0;
for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = 1;
for(; isdigit(ch); ch = getchar()) x = x * 10 + ch - 48;
if(f) x = -x;
}
const int N = 1000005, mod = 1e9 + 7;
char s[N], t[N];
int inv[N], js[N], pw[N], f[N], cnts, cntt, da, db, lens, lent, n, ans, total;
inline int Pow(int a, int b){
int ans = 1;
for(; b; b >>= 1, a = 1ll * a * a % mod)
if(b & 1) ans = 1ll * ans * a % mod;
return ans;
}
inline int C(int x, int y){
return 1ll * js[x] * inv[y] % mod * inv[x-y] % mod;
}
int main(){
scanf("%s", s + 1), scanf("%s", t + 1), read(n);
lens = strlen(s + 1), lent = strlen(t + 1);
for(int i = 1; i <= lens; i++){
if(s[i] == 'A') da++; if(s[i] == 'B') db++; if(s[i] == '?') cnts++;
}
for(int i = 1; i <= lent; i++){
if(t[i] == 'A') da--; if(t[i] == 'B') db--; if(t[i] == '?') cntt++;
}
inv[0] = js[0] = pw[0] = 1;
for(int i = 1; i <= n + 1; i++) pw[i] = 2ll * pw[i-1] % mod;
for(int i = 1; i <= lens + lent; i++)
js[i] = 1ll * js[i-1] * i % mod, inv[i] = Pow(js[i], mod - 2);
for(int i = n; i; i--){
f[i] = 1ll * (n / i) * (n / i) % mod;
for(int j = i + i; j <= n; j += i) (f[i] += mod - f[j]) %= mod;
total = (total + 1ll * f[i] * pw[i] % mod) % mod;
}
for(int d = -cntt; d <= cnts; d++){
int A = da + d, B = db + cnts - cntt - d, x = C(cnts + cntt, cntt + d);
if(!A && !B) (ans += 1ll * x * total % mod) %= mod;
if(1ll * A * B >= 0) continue;
int g = __gcd(abs(A), abs(B));
A = abs(A) / g, B = abs(B) / g;
(ans += (1ll * x * (pw[n/max(A,B)+1] - 2) + mod) % mod) %= mod;
}
if(lens == lent){
int flag = 1, res = 1;
for(int i = 1; i <= lens; i++){
if(s[i] != '?' && t[i] != '?' && s[i] != t[i]) flag = 0;
if(s[i] == '?' && t[i] == '?') res = 2ll * res % mod;
}
if(!flag) return cout << ans << endl, 0;
(ans += 1ll * res * (1ll * (pw[n+1] - 2) * (pw[n+1] - 2) % mod - total) % mod) %= mod;
ans = (ans % mod + mod) % mod;
}
cout << ans << endl;
return 0;
}

CodeForces 794 G.Replace All的更多相关文章

  1. [codeforces 549]G. Happy Line

    [codeforces 549]G. Happy Line 试题描述 Do you like summer? Residents of Berland do. They especially love ...

  2. Codeforces 1207 G. Indie Album

    Codeforces 1207 G. Indie Album 解题思路 离线下来用SAM或者AC自动机就是一个单点加子树求和,套个树状数组就好了,因为这个题广义SAM不能存在 \(len[u] = l ...

  3. codeforces 659 G. Fence Divercity 组合数学 dp

    http://codeforces.com/problemset/problem/659/G 思路: f(i,0/1,0/1) 表示到了第i个,要被切的块开始了没有,结束了没有的状态的方案数 递推看代 ...

  4. Codeforces 803 G. Periodic RMQ Problem

    题目链接:http://codeforces.com/problemset/problem/803/G 大致就是线段树动态开节点. 然后考虑到如果一个点还没有出现过,那么这个点显然未被修改,就将这个点 ...

  5. Codeforces 954 G. Castle Defense

    http://codeforces.com/problemset/problem/954/G 二分答案 检验的时候,从前往后枚举,如果发现某个位置的防御力<二分的值,那么新加的位置肯定是越靠后越 ...

  6. Codeforces 746 G. New Roads

    题目链接:http://codeforces.com/contest/746/problem/G mamaya,不知道YY了一个什么做法就这样过去了啊 2333 首先我显然可以随便构造出一棵树满足他所 ...

  7. Codeforces 724 G Xor-matic Number of the Graph 线性基+DFS

    G. Xor-matic Number of the Graph http://codeforces.com/problemset/problem/724/G 题意:给你一张无向图.定义一个无序三元组 ...

  8. codeforces 626 G. Raffles(线段树+思维+贪心)

    题目链接:http://codeforces.com/contest/626/problem/G 题解:这题很明显买彩票肯定要买贡献最大的也就是说买p[i]*(num[i]+1)/(num[i]+a[ ...

  9. codeforces 794 C. Naming Company(贪心)

    题目链接:http://codeforces.com/contest/794/problem/C 题意:有两个人每个人都有一个长度为n的字符串,两人轮流拿出一个字符串,放在一个长度为n的字符串的指定位 ...

随机推荐

  1. UVALive - 4094 WonderTeam (贪心)

    题目大意: 有n支队伍,每两支队伍打两场比赛(主客场各一次),胜得3分,平得1分,输不得分,比赛结束之后会评选出一个梦之队,梦之队满足以下条件:进球总数最多,胜利场数最多,丢求总数最少,三个都不能并列 ...

  2. pandas 实现通达信里的MFI

    pandas 实现通达信里的MFI 算法里的关键点: combine()和rolling().sum()方法 combine -- 综合运算, rolling().sum() -- 滚动求和 利用pd ...

  3. ie8下jquery改变PNG的opacity出现黑边

    复制网上的,没有他们那个类型的博客,所以就直接复制了 这些天在做一个效果,鼠标经过,PNG图片由透明变成不透明,jquery代 码:$(element).animate({"opacity& ...

  4. Guava HashMultiset(MultiSet)

    multiset:多重集合,和set唯一的不同是 set 集合中一个值只能出现一次,而multiset多重集合中一个值可以出现多次.一个典型的应用就是统计单词出现次数 举例: public class ...

  5. python中的 __repr__和__str__

    __repr__,被内置函数repr用于把一个对象用"官方"的字符串形式表示出来(终端友好)    1.值传给eval()来返回一个对象的字符串表示形式    2.否则返回一个尖括 ...

  6. 基于FPGA(DDS)的正弦波发生器

    记录背景:昨晚快下班时,与同事rk聊起怎么用FPGA实现正弦波的输出.我第一反应是利用高频的PWM波去滤波,但感觉这样的波形精度肯定很差:后来想起之前由看过怎么用FPGA产生正弦波的技术,但怎么都想不 ...

  7. 使用pt-table-checksum校验MySQL主从复制【转】

    pt-table-checksum是一个基于MySQL数据库主从架构在线数据一致性校验工具.其工作原理在主库上运行, 通过对同步的表在主从段执行checksum, 从而判断数据是否一致.在校验完毕时, ...

  8. 用Java检测远程主机是否能被连接

    有人推荐使用java的Runtime.exec()方法来直接调用系统的Ping命令.也有人完成了纯Java实现Ping的程序,使用的是Java的NIO包(native io, 高效IO包).我个人认为 ...

  9. java虚拟机规范(se8)——java虚拟机结构(二)

    2.5 运行时数据区域 java虚拟机定义了多个用于程序执行期间的运行时数据区域.这些数据区域中一些随着java虚拟机的启动而创建,随着虚拟机的退出而销毁.其他的数据区域时和线程相关的.线程相关数据区 ...

  10. Newtonsoft 反序列化字符串

    string json=“[{“name”:”zhangsan”,”age”:”12”},{“name”:”zhangsan”,”age”:”12”}]” 方法1: JArray arr = (JAr ...