MG loves string

MG loves string

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)

Problem Description
MG is a busy boy. And today he's burying himself in such a problem:

For a length of N, a random string made of lowercase letters, every time when it transforms, all the character i will turn into a[i].

MG states that the a[i] consists of a permutation .

Now MG wants to know the expected steps the random string transforms to its own.

It's obvious that the expected steps X will be a decimal number.
You should output X26Nmod 1000000007.
 

 

Input
The first line is an integer T which indicates the case number.(1<=T<=10)

And as for each case, there are 1 integer N in the first line which indicate the length of random string(1<=N<=1000000000).

Then there are 26 lowercase letters a[i] in the next line.
 

 

Output
As for each case, you need to output a single line.

It's obvious that the expected steps X will be a decimal number.
You should output X26Nmod 1000000007.
 

 

Sample Input
2 2 abcdefghijklmnpqrstuvwxyzo 1 abcdefghijklmnopqrstuvwxyz
 

 

Sample Output
5956 26
 
分析:首先,这些字母作映射变换,构成若干个封闭的环;
   其次,环的大小的不同个数不超过6个,因为1+2+3+4+5+6+7>26;
   然后按环的大小分类,得到数组b,表示需要变换i次的字母个数;
   接着状压枚举,问题转化为n个数满足若干不相交集合中每个集合中至少一个元素出现过的方案数;
   而这个问题容斥解决;
代码:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <climits>
#include <cstring>
#include <string>
#include <set>
#include <bitset>
#include <map>
#include <queue>
#include <stack>
#include <vector>
#define rep(i,m,n) for(i=m;i<=n;i++)
#define mod 1000000007
#define inf 0x3f3f3f3f
#define vi vector<int>
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define ll long long
#define pi acos(-1.0)
#define pii pair<int,int>
#define sys system("pause")
const int maxn=1e5+10;
const int N=2e5+10;
using namespace std;
ll gcd(ll p,ll q){return q==0?p:gcd(q,p%q);}
ll qpow(ll p,ll q){ll f=1;while(q){if(q&1)f=f*p%mod;p=p*p%mod;q>>=1;}return f;}
int n,m,k,t,a[10],b[10],qu[10],id[30],tot;
bool vis[27];
char s[27];
ll ret;
int main()
{
    int i,j;
    scanf("%d",&t);
    while(t--)
    {
        memset(vis,false,sizeof(vis));
        memset(id,-1,sizeof(id));
        ret=0;
        tot=0;
        scanf("%d%s",&n,s);
        for(i=0;i<26;i++)
        {
            if(!vis[i])
            {
                int cnt=0;
                int now=i;
                while(!vis[now])cnt++,vis[now]=true,now=s[now]-'a';
                if(id[cnt]==-1)a[tot]=cnt,b[tot]=cnt,id[cnt]=tot++;
                else b[id[cnt]]+=cnt;
            }
        }
        for(i=0;i<(1<<tot);i++)
        {
            ll lc=1;
            int cnt=0;
            for(j=0;j<tot;j++)
            {
                if(i>>j&1)lc=lc/gcd(a[j],lc)*a[j],qu[cnt++]=j;
            }
            ll tmp=0;
            for(j=0;j<(1<<cnt);j++)
            {
                int now=0,num=0;
                for(k=0;k<cnt;k++)
                {
                    if(j>>k&1)num++,now+=b[qu[k]];
                }
                if((cnt-num)&1)tmp=(tmp-qpow(now,n)+mod)%mod;
                else tmp=(tmp+qpow(now,n))%mod;
            }
            (ret=ret+lc*tmp%mod)%=mod;
        }
        printf("%lld\n",ret);
    }
    return 0;
}
posted @ 2017-04-02 02:30  mxzf0213  阅读(496)  评论(0编辑  收藏  举报