您的位置:首页 > 其它

AtCoder Regular Contest 064 F - Rotated Palindromes 乱搞

2018-02-26 20:48 393 查看

题意

给出n和k,问有多少个序列可以由长度为n且元素均在[1,k]范围内的回文串旋转得到。

n,k<=10^9

分析

这种题的套路一般就是枚举周期。

设f[i]f[i]表示周期为i的回文串数量。

那么f[i]=ki+12−∑j|i,j<if[j]f[i]=ki+12−∑j|i,j<if[j]

显然周期为i的回文串可以旋转出i个不同的序列。

因为周期为偶数的串后移i/2位后周期不变,所以会被算两次。

代码

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;

typedef long long LL;

const int N=3005;
const int MOD=1000000007;

int n,k,tot,a
,f
;

int ksm(int x,int y)
{
int ans=1;
while (y)
{
if (y&1) ans=(LL)ans*x%MOD;
x=(LL)x*x%MOD;y>>=1;
}
return ans;
}

int main()
{
scanf("%d%d",&n,&k);
for (int i=1;i*i<=n;i++)
if (n%i==0)
{
a[++tot]=i;
if (i*i<n) a[++tot]=n/i;
}
sort(a+1,a+tot+1);
int ny2=ksm(2,MOD-2),ans=0;
for (int i=1;i<=tot;i++)
{
f[i]=ksm(k,(a[i]+1)/2);
for (int j=1;j<i;j++)
if (a[i]%a[j]==0) (f[i]+=MOD-f[j])%=MOD;
if (a[i]&1) (ans+=(LL)f[i]*a[i]%MOD)%=MOD;
else (ans+=(LL)f[i]*a[i]%MOD*ny2%MOD)%=MOD;
}
printf("%d",ans);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: