P6825 「EZEC-4」求和题解
给定
推式子:
发现可以后面是一个等比序列,可以
上代码:
#include<bits/stdc++.h>
using namespace std;
const int N=1500050;
bool prime[N];
int zs[N],mu[N],idx;
int n,p,t[N];
void init()
{
mu[1]=1;
for(int i=2;i<=N-50;i++)
{
if(!prime[i]) zs[++idx]=i,mu[i]=-1;
for(int j=1;j<=idx&&zs[j]*i<=N-50;j++)
{
prime[zs[j]*i]=true;
if(i%zs[j]==0) break;
mu[zs[j]*i]=-mu[i];
}
}
}
int ksm(int ds,int zs)
{
ds=ds%p;
int re=1;
while(zs)
{
if(zs&1) re=1ll*re*ds%p;
ds=1ll*ds*ds%p;
zs=zs/2;
}
return re;
}
int calc(int x,int y)
{
if(y==1) return x;
int re=calc(x,y/2);
re=(re+1ll*re*ksm(x,y/2)%p)%p;
if(y&1) re=(re+1ll*x*ksm(x,y-1)%p)%p;
return re;
}
int Calc(int x,int y)
{
int re=calc(x,y);
return 1ll*re*re%p;
}
int ssolve(int n,int d)
{
int re=0;
for(int l=1;l<=n;l++)
{
if(!mu[l]) continue;
re=((re+1ll*mu[l]*Calc(ksm(d,l),n/l)%p)%p+p)%p;
}
return re;
}
int solve(int n)
{
int re=0;
for(int l=1;l<=n;l++)
re=((re+ssolve(n/l,ksm(l,l)))%p+p)%p;
return re;
}
int main()
{
init();
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d %d",&n,&p);
printf("%d\n",solve(n));
}
return 0;
}