説明
しかし、ゲームを作るにはまっ小さなCに、彼は完全にナショナルチームの一つとして自分自身を忘れてしまった、彼は仕事のタイトルを完了するのを待っている156があります。仕事オフに行く別の日、彼は行っていなかったタイトル。彼はすぐに、最も簡単な質問の外観を拾いました。
ストリングは、いわゆるサイクリックシフトの長さによって、巡回シフト後に得られたNパリンドローム配列であることができるように「整数Nを考えると、あなたは、K列の1の間の整数であり、どのくらいのキャラクタ・セットの決定しますそれは、「1221」などの文字列を、巡回シフトが「1221」、「2211」、「2112」、「1122」4つの文字列とすることができるの終わりに(空であってもよい)接頭文字列である。結果モジュロ109 + 7」
チームはCCF小さなCがキャンセルされた資格を維持するために、あなたは今、この質問で彼を助けます。
入力
最初の行は二つの整数N、Kが含まれています
出力
出力列の数は、109の+ 7モジュロ結果の条件を満たすために。
サンプル入力
サンプル入力1
4 2
サンプル入力2
1 10
サンプル入力3
6 3
サンプル入力4
1000000000 1000000000
サンプル出力
サンプル出力1
6
サンプル出力2
10
サンプル出力3
75
サンプル出力4
875699961
ヒント
最初のサンプルでは、 "1111"、 "1122"、 "1221"、 "2211"、 "2112"、 "2222"、6対象の文字列があります。
まずパリンドローム配列がパリンドロームであるとして列挙パリンドローム配列を考えるので、我々は半分だけパリンドローム配列の列挙、パリンドローム配列の数である\(M ^ {(N + 1)/ 2} \) 。
各文字列は回文でなければなりません\(N \)巡回シフト後の文字列に種が、重複があるため、この計算した後、私たちは、答えよりも、それははるかに大きいでしょう。
我々は、ループ部回文配列を列挙することができ、繰り返し文字列の数を計算する方法を考えていません。
2つのケースが議論しました。
1ブロックは、奇数サイクルであります
円形断面は、パリンドローム配列がパリンドローム配列である必要があるため、する巡回シフト部の一の周期の我々の長さ(LEN \)を\が繰り返されるので、生成されます\(LEN \)新しい文字列を。
前記ループ部が偶数であります
私たちがしているようので、上記の理由により、ループ部は、限り、回文である必要があります\(/ 2 \ LEN)繰り返される長さに。
例えば、文字列\(122 111 221 \)その後、我々は2つのシフトは、文字列となる\(21122112 \)を見て、元のシリーズと同じではないが、我々は金意志回文文字列を列挙します以下のために\(21122112 \) 、それが繰り返さ考えられています。
次DP。
前処理してみましょう\(N- \)すべての要因、\([] \は)
我々は、セット\を(DP [I] \)セクションの最小サイクル表す([I] \)\の場合適格パリンドローム配列の数。
我々は(DP [I] \)\減算\(DP [[I]ファクター] \)を保証するために、\([I] \)セクションの最小サイクルタイムを。
文字列の文字列番号に直接ANS回文を拠出することができます。
#include<bits/stdc++.h>
#define mod 1000000007
#define int long long
using namespace std;
int dp[2010],cnt,n,k,a[2010],ans;
int fastpow(int x,int y)
{
int sum=1;
while(y)
{
if(y&1)
{
sum=(1ll*sum*x)%mod;
}
x=(1ll*x*x)%mod;
y>>=1;
}
return sum;
}
signed main()
{
scanf("%lld%lld",&n,&k);
for(int i=1;i*i<=n;i++)//枚举因子
{
if(n%i==0)
{
a[++cnt]=i;
if(i*i!=n)
{
a[++cnt]=n/i;
}
}
}
sort(a+1,a+cnt+1);
for(int i=1;i<=cnt;i++)
{
dp[i]=fastpow(k,(a[i]+1)/2);//有多少个回文串
for(int j=1;j<i;j++)
{
if(a[i]%a[j]==0)//去重
{
dp[i]=(dp[i]-dp[j]+mod)%mod;
}
}
if(a[i]&1)//统计答案
{
ans=(ans+dp[i]*a[i])%mod;
}else{
ans=(ans+dp[i]*(a[i]/2))%mod;
}
}
printf("%lld\n",ans);
return 0;
}