傳送門
題解:
倒着思考,什麼樣的序列必勝?首先是全0序列,然後是全等序列,然後是差分後是全等序列的。。。以此類推,必勝的序列必然滿足它的某一階差分在 %p 下是全0,且最少的差分次數就是答案。
以下將差分定義爲 ,這裏省略了下標的取模,默認 是一個循環序列。
首先我們知道一個差分後是數列可以寫成
考慮 的情況,用 Lucas 定理消去爲0的組合數,我們發現這個時候 。
假設 能夠最終差分爲全,次數爲 ,則必然存在某個 ,使得差分 之後序列爲全0,則 ,即 。
我們發現限制容易變成 ,那麼將 變大我們發現最大隻需要考慮 ,再往上就沒有意義了,這個時候看一下原序列是否滿足條件,滿足則有解,否則無解。
求答案就很簡單了,我們把 變爲循環節長度 ,考慮進行若干次 次差分,直到循環節長度變爲 ,可以證明覆雜度上界是等比數列求和爲 。
代碼:
#include<bits/stdc++.h>
#define ll long long
#define re register
#define cs const
namespace IO{
inline char gc(){
static cs int Rlen=1<<22|1;static char buf[Rlen],*p1,*p2;
return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,Rlen,stdin),p1==p2)?EOF:*p1++;
}template<typename T>T get_integer(){
char c;bool f=false;while(!isdigit(c=gc()))f=c=='-';T x=c^48;
while(isdigit(c=gc()))x=((x+(x<<2))<<1)+(c^48);return f?-x:x;
}inline int gi(){return get_integer<int>();}
}using namespace IO;
using std::cerr;
using std::cout;
cs int N=3e5+7;
int n,p;
int A[N],B[N];
bool check(int t){
for(int re i=0;i+t<n;++i)
if(A[i]!=A[i+t])return false;
return true;
}
void Main(){
n=gi(),p=gi();
for(int re i=0;i<n;++i)
A[i]=gi()%p;
int t=1;
while(n%(t*p)==0)t*=p;
if(!check(t)){
puts("-1");
return ;
}int ans=0;
while(t>1){
n=t;t/=p;
while(!check(t)){ans+=t;
for(int re i=0;i<n;++i)
B[i]=(A[i]-A[(i+t)%n]+p)%p;
memcpy(A,B,sizeof(int)*n);
}
}cout<<ans+!!A[0]<<"\n";
}
inline void file(){
#ifdef zxyoi
freopen("game.in","r",stdin);
#endif
}signed main(){file();Main();return 0;}