• 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

  • 相关阅读:
    巨人的崛起 Android操作系统发展历程
    iPhone 4S定位功能加强 支持GLONASS系统
    android子线程更新UI,与主Thread一起工作
    什么在阻碍移动互联网的普及?
    WEB.CONFIG 配置详解
    解决在aspx页面上进行传中文参数时会出现乱码问题
    VS2005水晶报表注册码
    windows2003应用程序池假死的问题
    浅谈ASP.NET内部机制
    合理建立数据库索引
  • 原文地址:https://www.cnblogs.com/neighthorn/p/6652805.html
Copyright © 2020-2023  润新知