CodeForces - 520C
Vasya became interested in bioinformatics. He's going to write an article about similar cyclic DNA sequences, so he invented a new method for determining the similarity of cyclic sequences.
Let's assume that strings s and t have the same length n, then the function h(s, t) is defined as the number of positions in which the respective symbols of s and t are the same. Function h(s, t) can be used to define the function of Vasya distance ρ(s, t):
Vasya found a string s of length n on the Internet. Now he wants to count how many strings t there are such that the Vasya distance from the string s attains maximum possible value. Formally speaking, t must satisfy the equation: .
Vasya could not try all possible strings to find an answer, so he needs your help. As the answer may be very large, count the number of such strings modulo 109 + 7.
The first line of the input contains a single integer n (1 ≤ n ≤ 105).
The second line of the input contains a single string of length n, consisting of characters "ACGT".
OutputPrint a single number — the answer modulo 109 + 7.
Examples1 C
1
2 AG
4
3 TTT
1
Please note that if for two distinct strings t1 and t2 values ρ(s, t1) и ρ(s, t2) are maximum among all possible t, then both strings must be taken into account in the answer even if one of them can be obtained by a circular shift of another one.
In the first sample, there is ρ("C", "C") = 1, for the remaining strings t of length 1 the value of ρ(s, t) is 0.
In the second sample, ρ("AG", "AG") = ρ("AG", "GA") = ρ("AG", "AA") = ρ("AG", "GG") = 4.
In the third sample, ρ("TTT", "TTT") = 27
其实就是二重循环内循环字符串s不变,字符串t第一个元素每次移到最后一个,然后求h(),外循环s每次首字符移到最后然后再进行内循环,求这些h()函数总和。就如题目中给的例子
题目让求有多少种t使得这个p()最大
思路:这道题一开始就被题目吓到了,一直到比赛结束也没有想到思路。搜题解发现这是一个找规律的题目,题目让求有多少种t使得这个p()最大,首先我们的任务就是要知道在知道s的情况下p()的最大值是多少
观察发现它的最大值只取决于s字符串中某个出现次数最多的字符个数,为什么这么说呢?
举个例子AAACGT这个字符串我们发现次数最多的是A,那么对于
s:A A A C G T 最大的情况一定是
t:A A A A A A 因为每一个A都可以匹配三次,那么也就是在一次内循环中(t变换时)
每个A可以匹配三次那么一次内循环h()的总和应该是3*n,假如说字符串中有别的字符,那么这个字符在t循环变换的过程中这个字符可以匹配的总次数等于这个字符在s串中的个数,一定小于出现最多的那个次数,比如有C那么t串变化一个循环,C最多可以匹配一次,小于3,那么总的也一定小于3*n;再加上外循环,其实无所谓每次都是3*n,所以是最大值3*n*n。
另外一个例子加入最多出现次数的字符有多个是什么情况呢
s:A A A C C C G T 其实可以这样想,因为这么一个字符串中字符最大出现次数是3
即使有多个出现3的,但是我们t字符串中的字符能和s匹配的字符的最大次数还是3次,不会因为有多个最大出现次数而改变,而会改变的就是我们有了更多的选择方案
为了让p()函数最大,我们就会希望每个字符的匹配次数都是最大值,也就是都是都是s串中字符出现的最大次数,那么我们只要在其中最大出现次数的字符中任选一个即可
s : A A A C C C G T
t:A C C A C A C C
t : C C A C A A A A
t: _ _ _ _ _ _ _ _
……
所以这样每个字符的再一次变换循环中最大匹配次数都是s中字符出现次数的最大值
所以说到这里估计大家就可以看到大体思路了,每个位置我们又几个最大出现次数的字符就有几种选择x,一共n个位置,总共t可以满足最大值的种类就有x^n中
最终就转化成了求快速幂,哎感叹自己思维辣鸡啊
code:
#include
#include
#include
using namespace std;
typedef long long ll;
const int mod = 1e9+7;
const int maxn = 1e5+10;
int n;
char s[maxn];
int vis[4];
ll q_pow(ll a, ll b){
ll ans = 1LL;
while(b){
if(b & 1)
ans = ans * a % mod;
b >>= 1;
a = a * a % mod;
}
return ans;
}
int main(){
memset(vis,0,sizeof(vis));
scanf("%d",&n);
scanf("%s",s);
for(int i = 0; i < n; i++){
if(s[i] == 'A') vis[0]++;
if(s[i] == 'C') vis[1]++;
if(s[i] == 'G') vis[2]++;
if(s[i] == 'T') vis[3]++;
}
int maxcnt = 0;
int cnt = 0;
for(int i = 0; i < 4; i++){
maxcnt = max(maxcnt,vis[i]);
}
for(int i = 0; i < 4; i++){
if(vis[i] == maxcnt) cnt++;
}
printf("%lld\n",q_pow((ll)cnt,(ll)n));
return 0;
}