致歉信
我作为博主,没有实时更新这片博客,感到很抱歉。
题目
求
其中,
的最小值因子不超过
。
有多组数据。数据数小于等于3000.
题解
这道题目的部分分很好拿,但就是坑。
对于
,直接上一波斯特林数就好了。
什么,没拿到应有的分数?!
检查后发现,是在预处理
漏了快速加。
所以对于每个乘号都要检查。
对于
,直接快速幂肯定会T。
我竟然漏想了线筛?!
其实不用快速加,直接看下面一段过程。
LL ksj(LL x,LL y){
x%=m;y%=m;
LL tmp=(LL)((DB)x*y/m+1e-8)*m;
return (x*y-tmp+m)%m;
}
由于
和
溢出的部分是一样的,所以他俩相减之后对答案没有影响了。
加上
,是为了避免精度问题。
然后就可以愉快地线筛了。
LL ksm(LL x,LL y){
LL rs=1;x%=m;
for(;y;y>>=1,x=ksj(x,x))if(y&1)rs=ksj(rs,x);
return rs;
}
void pre(){
LL i,j;
f[1]=1;
fo(i,2,N-10){
if(!bz[i]){
pri[++pri[0]]=i;
f[i]=ksm(i,k);
}
fo(j,1,pri[0]){
if(i*pri[j]>N-10)break;
bz[i*pri[j]]=1;
f[i*pri[j]]=ksj(f[i],f[pri[j]]);
if(i%pri[j]==0)break;
}
}
}
接下来还有这一档部分分:
。
即
的质因数两两互不相同。
直接用中国剩余定理搞一波得了。
重新说一遍中国剩余定理吧。
假设现在方程组内有k个方程:
……
设
则在模
的情况下有唯一解。
这是我的70分代码。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define N 10000010
#define M 100010
#define DB long double
#define LL long long
#define fo(i,a,b) for(i=a;i<=b;i++)
#define fd(i,a,b) for(i=a;i>=b;i--)
using namespace std;
LL sum[N],qu[M];
LL m,k,kk,T,n,x,i,j,mx,ans,temp;
LL A1,A2;
LL s1[N],S[1002][1002];
LL f[N],pri[N],cnt;
LL p[N],b[M],t[N],a[N];
bool bz[N];
LL ksj(LL x,LL y,LL m){
x%=m;y%=m;
LL tmp=(LL)((DB)x*y/m+1e-8)*m;
return (x*y-tmp+m)%m;
}
void pres(){
LL i,j;
S[0][0]=1;
fo(i,1,1000)fo(j,1,i)S[i][j]=(S[i-1][j-1]+ksj(S[i-1][j],i-1,m))%m;
}
LL ksm(LL x,LL y,LL m){
LL rs=1;x%=m;
for(;y;y>>=1,x=ksj(x,x,m))if(y&1)rs=ksj(rs,x,m);
return rs;
}
LL get1(LL n,LL k){
LL rs=1,i;
fd(i,n,n-k+1){
if(i%k==0){
rs=ksj(rs,i/k,m);
}else rs=ksj(rs,i,m);
}
return rs%m;
}
void pre(){
LL i,j;
f[1]=1;
fo(i,2,N-10){
if(!bz[i]){
pri[++pri[0]]=i;
f[i]=ksm(i,k,m);
}
fo(j,1,pri[0]){
if(i*pri[j]>N-10)break;
bz[i*pri[j]]=1;
f[i*pri[j]]=ksj(f[i],f[pri[j]],m);
if(i%pri[j]==0)break;
}
}
}
void pre1(){
LL i,j;
f[1]=1;
fo(i,2,300000){
if(!bz[i]){
pri[++pri[0]]=i;
f[i]=ksm(i,k,m);
}
fo(j,1,pri[0]){
if(i*pri[j]>300000)break;
bz[i*pri[j]]=1;
f[i*pri[j]]=ksj(f[i],f[pri[j]],m);
if(i%pri[j]==0)break;
}
}
}
void work(LL n){
LL i;
fo(i,1,cnt){
A1=sum[p[i]];
A2=sum[n%p[i]];
b[i]=(ksj(A1,n/p[i],p[i])+A2)%p[i];
}
ans=0;
fo(i,1,cnt){
ans=(ans+ksj(ksj(a[i],b[i],m),t[i],m))%m;
}
printf("%lld\n",ans);
}
int main(){
scanf("%lld%lld%lld",&m,&k,&T);
fo(i,1,T)scanf("%lld",&qu[i]),mx=max(mx,qu[i]);
if(mx<=10000000){
pre();
fo(i,1,10000000)sum[i]=(sum[i-1]+f[i])%m;
fo(i,1,T)printf("%lld\n",sum[qu[i]]);
return 0;
}
if(k<=1000){
pres();
fo(i,1,T){
n=qu[i];
ans=0;
s1[0]=n%m;
fo(kk,1,k){
s1[kk]=get1(n+1,kk+1);
fo(j,0,kk-1){
temp=ksj(S[kk][j],s1[j],m);
s1[kk]=(s1[kk]-((j+kk)&1?-1:1)*temp%m+m)%m;
}
}
ans=s1[k]%m;
printf("%lld\n",ans);
}
return 0;
}
pre1();
fo(i,1,300000)sum[i]=(sum[i-1]+f[i])%m;
x=m;
fo(i,1,25997)if(x%pri[i]==0){
if(x%(pri[i]*pri[i])==0){
printf("0");
return 0;
}
a[++cnt]=m/pri[i];
p[cnt]=pri[i];
t[cnt]=ksm(a[cnt],p[cnt]-2,p[cnt]);
x/=pri[i];
if(x==1)break;
}
fo(i,1,T)work(qu[i]);
return 0;
}