题解
题目要求n个范围在[1,L]的数任意排列的最小公倍数的和。
将每个数拆成
pk11∗pk22∗...∗pknn
p
1
k
1
∗
p
2
k
2
∗
.
.
.
∗
p
n
k
n
的形式,p为质因子。
现在就分别对每个质数计算。
考虑一个质数p,当它的次数为k的时候,有多少种可能。
那么就至少存在某个数的这个质数的次数为k,最大值必须为k。
于是方案数就是:
(l−(l/(pk+1))n−(l−(l/pk))n)
(
l
−
(
l
/
(
p
k
+
1
)
)
n
−
(
l
−
(
l
/
p
k
)
)
n
)
现在就是计算的问题了,
对质数p进行分类,
当p<
l√
l
的时候,就直接计算,枚举k。
当p>
l√
l
的时候,很显然k只能为1。
式子就变为了:
(ln−(l−(l/p))n)
(
l
n
−
(
l
−
(
l
/
p
)
)
n
)
现在上面的系数只与l/p有关,
于是就可以直接分块做。
code
#include <queue>
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string.h>
#include <cmath>
#include <math.h>
#include <time.h>
#define ll long long
#define N 5000003
#define M 103
#define db double
#define P putchar
#define G getchar
#define inf 998244353
#define pi 3.1415926535897932384626433832795
using namespace std;
char ch;
void read(ll &n)
{
n=0;
ch=G();
while((ch<'0' || ch>'9') && ch!='-')ch=G();
ll w=1;
if(ch=='-')w=-1,ch=G();
while('0'<=ch && ch<='9')n=(n<<3)+(n<<1)+ch-'0',ch=G();
n*=w;
}
int max(int a,int b){return a>b?a:b;}
int min(int a,int b){return a<b?a:b;}
ll abs(ll x){return x<0?-x:x;}
ll sqr(ll x){return x*x;}
void write(ll x){if(x>9) write(x/10);P(x%10+'0');}
bool bz[N];
ll ss[400000];
ll ksm(ll x,ll y,ll mo)
{
ll s=1;
for(;y;y>>=1,x=x*x%mo)
if(y&1)s=s*x%mo;
return s;
}
void pre()
{
memset(bz,1,sizeof(bz));
for(int i=2;i<N;i++)
{
if(bz[i])ss[++ss[0]]=i;
for(int j=1;j<=ss[0] && ss[j]*i<N;j++)
{
bz[i*ss[j]]=0;
if(i%ss[j]==0)break;
}
}
}
ll n,m,l,p,T,w,s,t,ans;
int main()
{
freopen("pupil.in","r",stdin);
freopen("pupil.out","w",stdout);
for(pre(),read(p),read(T);T;T--)
{
read(n);read(l);
m=sqrt(l);ans=1;
for(w=1;ss[w]<=m;w++)
{
s=ss[w];
for(int k=1;s<=l;k++)
{
t=(ksm(l-l/(s*ss[w]),n,p-1)-ksm(l-l/s,n,p-1)+p-1)%(p-1);
ans=ans*ksm(s,(t+p-1)%(p-1),p)%p;
s=s*ss[w];
}
}
for(s=ss[w],t=l/s,w++;ss[w]<=l;w++)
{
if(t==l/ss[w])s=s*ss[w]%p;else
{
ans=ans*ksm(s,(ksm(l,n,p-1)-ksm(l-t,n,p-1)+p-1)%(p-1),p)%p;
s=ss[w];t=l/s;
}
}
ans=ans*ksm(s,(ksm(l,n,p-1)-ksm(l-t,n,p-1)+p-1)%(p-1),p)%p;
write(ans),P('\n');
}
return 0;
}