Description
Solution
我们发现最后的答案是前K个的次幂相乘的形式
于是可以矩阵乘法求出对应的指数
指数可能会爆,并且底数与模数不一定互质
那么用扩展欧拉定理
xc≡{xc,xc%φ(m)+φ(m),c<mc≥m(modm)
只需要在里面加个变量判断是否超过 φ(m) 即可
但是m很大,所以求 φ <script type="math/tex" id="MathJax-Element-122">φ</script>要用pollard_rho
Code
#include <cstdio>
#include <iostream>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fod(i,a,b) for(int i=a;i>=b;i--)
#define N 11
#define LL long long
using namespace std;
LL a[N],m,n,mo,pr[70],md,l,sv;
int d[5]={2,3,5,7,10007};
bool pd;
LL ksd(LL x,LL y,LL md)
{
if(y==0||x==0)return 0;
LL s=ksd(x,y/2,md);
if(s+s>md) pd=1;
return(y%2)?((s+s)%md+x)%md:(s+s)%md;
}
struct node
{
LL a[N][N];
friend node operator *(node x,node y)
{
node z;
memset(z.a,0,sizeof(z.a));
fo(i,1,m)
{
fo(j,1,m)
{
fo(k,1,m) z.a[i][j]=(z.a[i][j]+ksd(x.a[i][k],y.a[k][j],md))%md;
}
}
return z;
}
}s,sq;
node ksm(node k,LL n)
{
node s=k;
n--;
for(;n;k=k*k,n>>=1) if(n&1) s=s*k;
return s;
}
LL km(LL k,LL n,LL mo)
{
LL s=1;
for(;n;k=ksd(k,k,mo),n>>=1) if(n&1) s=ksd(s,k,mo);
return s;
}
LL gcd(LL x,LL y)
{
return(!y)?x:gcd(y,x%y);
}
LL rd(LL k)
{
return ((rand()*rand()%k*rand()%k*rand()%k)+rand())%k;
}
bool pd1(LL k)
{
fo(i,0,4)
{
if(k==d[i]) return 1;
if(k%d[i]==0) return 0;
LL t,n=k-1;
while((n&1)==0) n>>=1;
t=km(d[i],n,k);
while(n<k-1&&t!=1&&t!=k-1) t=ksd(t,t,k),n<<=1;
if(!((n&1)||t==k-1)) return 0;
}
return 1;
}
LL get(LL k)
{
LL c=rd(1e9)+1,r,x,y,i=1,n=2;
x=y=rd(k-1)+1;
while(1)
{
i++;
x=(ksd(x,x,k)+c)%k;
if(x==y) return k;
r=gcd(abs(x-y),k);
if(1<r&&r<k) return r;
if(i==n) y=x,n<<=1;
}
}
void fd(LL k)
{
if(k==1) return;
if(pd1(k))
{
pr[++pr[0]]=k;
return;
}
LL p=k;
while(p==k&&p!=1) p=get(k);
fd(k/p),fd(p);
}
int main()
{
int t;
cin>>t;
while(t--)
{
scanf("%lld%lld%lld",&m,&n,&mo);
fo(i,1,m) scanf("%lld",&a[i]),a[i]%=mo;
l=0;
if(n<=100000)
{
if(n<=m) printf("%lld\n",a[n]);
else
{
int w=1;
LL s;
fo(i,m+1,n)
{
s=1;
fo(j,1,m) s=s*a[j]%mo;
a[w]=s;
w=w%m+1;
}
printf("%lld\n",s);
}
}
else
{
md=1;
LL m1=mo,lm=sqrt(mo);
memset(sq.a,0,sizeof(sq.a));
pr[0]=0;
fd(mo);
sort(pr+1,pr+pr[0]+1);
md=pr[1]-1;
fo(i,2,pr[0])
{
if(pr[i]!=pr[i-1]) md=md*(LL)(pr[i]-1);
else md=md*pr[i];
}
fo(i,1,m-1) sq.a[i+1][i]=1;
fo(i,1,m) sq.a[i][m]=1;
pd=0;
sq=ksm(sq,n-m);
LL ans=1;
fo(i,1,m)
{
memset(s.a,0,sizeof(s.a));
s.a[1][i]=1;
s=s*sq;
ans=ksd(ans,km(a[i],s.a[1][m]+(pd)*md,mo),mo);
}
printf("%lld\n",(ans+mo)%mo);
}
}
}