题意:
给出一个字符串,字符串由"R","G","?"组成,若字符串存在2个R,且2个R中间是一个G,则称该串为“漂亮串”,现考虑将"?"替
换成"R"或"G"的所有字符串,求这些字符串中“漂亮串”的总数。
我们从反面考虑问题,若字符串不是“漂亮串”,则字符串的形式必然为:R...R...R...R,相邻2个R的距离相等且距离为奇
数。
所以我们可以枚举距离,构造“非漂亮串”,毛估总共需要枚举的次数为n*n*(1/1+1/2+...1/n),时间复杂度为O(n^2logn),然后
用总的字符串数(2^k,k为"?"总数)减去“非漂亮串”的总数,就是“漂亮串”的总数了。
解释:
就是我们把任意一个字符串s中的R全部提取出来(只考虑R),如果s不是beautiful string的话,那么所有的R一定具有解题思路里面那种形式
否则的话,就一定是beautiful string了,这个可以用反证法证明
反证分两步,证明相邻两个R距离不等以及存在距离为偶数
这个证明还是容易的
这样对每一个给定字符串,我们根据R的个数分别枚举距离就行了
/*
Pro: 0
Sol:
date:
*/
#include<cstdio>
#include<cstring>
using namespace std;
#define mod 1000000007
int t;
long long mod_pow(int a,int n,int p)
{
long long ret=1;
long long A=a;
while(n){
if (n & 1)
ret=(ret*A)%p;
A=(A*A)%p;
n>>=1;
}
return ret;
}
int main(){
scanf("%d",&t);
while( t -- ){
char str[808];
scanf("%s",str);
int len = strlen(str);
int unknown = 0, r_num = 0;
for(int i = 0; i < len; i ++){
if(str[i] == '?') unknown ++;
else if(str[i] == 'R') r_num ++;
}
long long unbea = (r_num == 0);//全为G的是不beautiful的。
for(int i = 0; i < len; i ++){//开始遍历
if(str[i] == 'R' || str[i] == '?'){//可能是R的情况
int x = (str[i] == 'R');
unbea = (unbea + (x == r_num) ) % mod;//这是给出的串只有一个R的情况
for(int dis = 1; dis + i < len; dis += 2){// + i 枚举距离
int y = x;
for(int sta = i + dis; sta < len; sta += dis){//枚举第二个位置以及以后
y += (str[sta] == 'R');
if(str[sta] == 'G') break;
unbea = (unbea + (y == r_num) )% mod;//如果遍历到的点和R的个数相同
//那么,就加上一个不美丽字符串
//这一句话包含了(拿样例4做解释)
//RRRR
//RRRG RRGG
//RGGR
//GRRR GRRG
//GGRR
}
}
}
}
printf("%I64d\n",mod_pow(2,unknown,mod) - unbea);
}
return 0;
}