[atARC064F]Rotated Palindromes
(长度为$n$的序列$a_{i}$,下标范围为$[0,n)$,且用字符串的方式即$a_{[l,r]}$来表示子区间)
定义一个长为$n$的序列$a_{i}$的周期为的$l$满足$l|n$且$\forall l\le i<n,a_{i}=a_{i+l}$(这里不同于普通周期的定义,普通周期定义是没有$l|n$这个要求的),最小正周期即为其中最小的正整数$l$
先考虑枚举一开始回文的$a_{i}$,再将其轮换来构造出所有$a_{i}$,可以证明具有这样两个性质:
1.若一个序列$a_{i}$是回文的,且$a_{i}$的最小正周期为$l$,则$a_{[0,l)}$也是回文的
2.若一个序列$a_{i}$是回文的,且$a_{i}$的最小正周期为$l$,分类讨论:
(1)若$l$为奇数,则将其轮换排列后,不存在与$a_{i}$不同的回文串
(2)若$l$为偶数,则将其轮换排列后,恰好存在一个与$a_{i}$相同的回文串
关于性质1,考虑$a_{[0,l)}=a_{[n-l,n)]}$即可,特别的,当$l=n$时显然也成立
关于性质2,下面来证明一下:
将$a_{i}$轮换后,当以$i\equiv j(mod\ l)$为起点时,两者是相同的,因此不妨假设起点在$[0,l)$中
若以$i$为起点($0<i<l$,当$i=0$时即$a_{i}$本身)时其为回文,不难得到$a_{k}=a_{i+(i-k)}=a_{2i-k}$(下标在模$n$意义下运算)
同时根据性质1,$a_{[0,l)}$自身回文,即$a_{k}=a_{2l-k}$,两式组合即$a_{k}=a_{2(l-i)+k}$
也就是说$2(l-i)$为$a_{i}$周期,同时$l$也是其周期,则$a_{i}$周期可以为$\gcd(l,2(l-i))$
(1)若$l$为奇数,$\gcd(l,2(l-i))=\gcd(l,l-i)<l$,显然矛盾
(2)若$l$为偶数,$\gcd(l,2(l-i))$在$i=\frac{l}{2}$时也是$l$,且显然此时也必然是回文的,因此恰好一个
根据性质2,我们考虑前面枚举回文的$a_{i}$来统计的方式,假设$a_{i}$最小正周期为$l$,则对于奇数的$l$其能提供$l$个不同的$a_{i}$(指最终的结果),对于偶数的$l$能提供$\frac{l}{2}$个$a_{i}$
问题即变为统计最小正周期为$l$的$a_{i}$个数,记为$f_{l}$,考虑如何计算:
性质1的逆命题也成立,即对于长为$n$且最小正周期为$l$的$a_{i}$,若$a_{[0,l)}$为回文,则$a_{i}$本身也是回文的
首先,长为$l$的回文的串一共有$k^{\lceil\frac{l}{2}\rceil}$个,接下来考虑减去最小正周期更小的$l$,也就是$\sum_{d|l,d<l}f_{d}$,显然最终所有状态都会是$n$的约数,转移复杂度即为$\sigma_{0}(n)^{2}$
当$n\le 10^{9}$,则$\sigma_{0}(n)\le 1344$(在$n=735134400$时取到),暴力dp即可
最终答案根据之前的性质2,也就是$\sum_{l|n,l为奇数}l\times f_{l}+\sum_{l|n,l为偶数}\frac{l}{2}\times f_{l}$
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 3005 4 #define mod 1000000007 5 int n,k,ans,a[N],f[N]; 6 int pow(int n,int m){ 7 int s=n,ans=1; 8 while (m){ 9 if (m&1)ans=1LL*ans*s%mod; 10 s=1LL*s*s%mod; 11 m>>=1; 12 } 13 return ans; 14 } 15 int main(){ 16 scanf("%d%d",&n,&k); 17 for(int i=1;i*i<=n;i++) 18 if (n%i==0)a[++a[0]]=i; 19 int m=a[0]; 20 for(int i=1;i<=m;i++)a[++a[0]]=n/a[m-i+1]; 21 for(int i=1;i<=a[0];i++){ 22 f[i]=pow(k,(a[i]+1)/2); 23 for(int j=1;j<i;j++) 24 if (a[i]%a[j]==0)f[i]=(f[i]+mod-f[j])%mod; 25 } 26 for(int i=1;i<=a[0];i++) 27 if (a[i]&1)ans=(ans+1LL*a[i]*f[i])%mod; 28 else ans=(ans+1LL*a[i]/2*f[i])%mod; 29 printf("%d",ans); 30 }