我作为博主,没有实时更新这片博客,感到很抱歉。
求 Σni=1ik(mod m) Σ i = 1 n i k ( m o d m )
其中, m m 的最小值因子不超过 300000 300000 。
有多组数据。数据数小于等于3000.
n,k,m≤1018 n , k , m ≤ 10 18
这道题目的部分分很好拿,但就是坑。
对于 k≤1000 k ≤ 1000 ,直接上一波斯特林数就好了。
什么,没拿到应有的分数?!
检查后发现,是在预处理 Si,j S i , j 漏了快速加。
所以对于每个乘号都要检查。
对于 n≤107 n ≤ 10 7 ,直接快速幂肯定会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;
}
由于 x∗y x ∗ y 和 tmp t m p 溢出的部分是一样的,所以他俩相减之后对答案没有影响了。
加上 10−8 10 − 8 ,是为了避免精度问题。
然后就可以愉快地线筛了。
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;
}
}
}
接下来还有这一档部分分: μ2(m)=1 μ 2 ( m ) = 1 。
即 m m 的质因数两两互不相同。
直接用中国剩余定理搞一波得了。
重新说一遍中国剩余定理吧。
假设现在方程组内有k个方程:
X≡a1 (mod p1) X ≡ a 1 ( m o d p 1 )
X≡a2 (mod p2) X ≡ a 2 ( m o d p 2 )
……
X≡ak (mod pk) X ≡ a k ( m o d p k )
设 Ai=mpi,Ti=Api−2i%pi A i = m p i , T i = A i p i − 2 % p i
则在模 m=Πki=1pi m = Π i = 1 k p i 的情况下有唯一解。
X≡Σki=1ai∗Ai∗Ti(mod m) X ≡ Σ i = 1 k a i ∗ A i ∗ T i ( m o d m )
这是我的70分代码。
#include
#include
#include
#include
#include
#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;
}