zoukankan      html  css  js  c++  java
  • 51Nod 1317 相似字符串对

    题目链接

    分析:

    考虑两个串的关系:$A+C=C+B$,我们观察可以发现,$A$和$B$是循环同构的,如果$A=G+H$,那么$B=H+G$,证明略长懒得写了...

    我们知道$A$串有$K^N$种,所以,我们只需要考虑对于所有的$A$串,有多少个$B$串可以和它构成合法的字符串对...如果我们不考虑重复的情况,有$N$种划分$A$串的方法...

    但是有重复的情况,考虑如何去重...

    我们假设$G$的长度为$p$和$q(p<q)$的时候$B$相等...那么有有以下的性质:

    $B:  A[p]A[p+1]A[p+2]......A[n-1]A[0]A[1]...A[p-1]$

    $B:  A[q]A[q+1]A[q+2]....A[n-1]A[0]A[1].....A[q-1]$

    我们定义$L$代表$q-p$

    那么对于任意的$A[i]$,都有$A[i]=A[(i+L)%n]$,诶,这就是循环节啊...也就是说,当$A$的最小循环节长度为$x$的时候,$A$串对应的$B$串有$x$个...

    所以,我们记$f[p]$代表长度为$p$的并且最小循环节就是它本身的字符串的合法方案...那么$ans=sum _{pmid n} p*f[p]$,至于$f[p]$的求法就是容斥啦...用总的方案数减去所有不和发的方案数,也就是枚举循环节长度并减去...因为一个数的因子一定是它的倍数的因子,所以我们需要求出的$f$的个数只有$n$的因子个数个...

    代码:

    #include<algorithm>
    #include<cstdio>
    #include<cmath>
    const int N=50000+5,M=1e9+7;
    int n,m,k,a,c,f[N],d[N];
    inline int p(int x,int y){
    	int r=1;
    	while(y){
    		if(y&1)r=1LL*r*x%M;
    		x=1LL*x*x%M,y>>=1;
    	}return r;
    }
    signed main(void){
    	scanf("%d%d",&n,&k);f[1]=k;m=sqrt(n);
    	for(int i=1;i<=m;i++)if(n%i==0){d[++c]=i;if(i*i!=n)d[++c]=n/i;}
    	std::sort(d+1,d+c+1);
    	for(int i=2;i<=c;i++){
    		f[i]=p(k,d[i]);
    		for(int j=1;j<i;j++)if(d[i]%d[j]==0)f[i]=(f[i]-f[j]+M)%M;
    	}
    	for(int i=1;i<=c;i++)a=(a+1LL*d[i]*f[i]%M)%M;printf("%d
    ",a);
    }
    

      


    By NeighThorn

  • 相关阅读:
    CSS三大特性
    CSS选择器
    CSS(1)
    多媒体标签
    快捷键
    H5注意点(2)
    H5注意点(1)
    List详解
    求最大子串和以及其中一个子串(java)
    隧道项目
  • 原文地址:https://www.cnblogs.com/neighthorn/p/6652805.html
Copyright © 2011-2022 走看看