借这题理解了tangjz的例题。。这题做法与那道题基本相同。
先来看一下最普通的做法:(以下均设 n≤m )
#include
#include
using namespace std;
#define Mod 20101009
typedef long long LL;
LL pow(int a,int x){
LL ans=1,prod=a;
for(;x;x>>=1,prod=prod*prod%Mod)
if(x&1)
ans=ans*prod%Mod;
return ans;
}
LL sf[10000005];
int prime[1000005];
bool p[10000005];
int main(){
int i,j;
sf[1]=1;
for(i=2;i<=10000000;++i){
if(!p[i])sf[i]=1-(prime[++prime[0]]=i);
for(j=1;j<=prime[0]&&i*prime[j]<=10000000;++j){
p[i*prime[j]]=1;
if(i%prime[j])sf[i*prime[j]]=sf[i]*(1-prime[j]);
else{
sf[i*prime[j]]=sf[i];
break;
}
}
}
//for(i=1;i<=20;++i)printf("%d:%I64d\n",i,sf[i]);
for(i=1;i<=10000000;++i)sf[i]=(sf[i-1]+sf[i]*i)%Mod;
int N,M,ans;
scanf("%d%d",&N,&M);
if(N>M)swap(N,M);
ans=0;
for(i=1;i<=N;){
j=i;
i=min(N/(N/i),M/(M/i))+1;
ans=(ans+(sf[i-1]-sf[j-1])*(N/j)%Mod*(N/j+1)%Mod*(M/j)%Mod*(M/j+1))%Mod;
}
cout<<(ans*pow(4,Mod-2)%Mod+Mod)%Mod;
}
杜教版:
#include
#include
using namespace std;
#include
#include
const int S=50000;
#define Mod 20101009
#define Mod6 120606054
bool p[50005];
int prime[10005];
typedef long long LL;
LL F[2][205],inis[50005],sg[50005];
LL pow(int a,int x){
LL ans=1,prod=a;
for(;x;x>>=1,prod=prod*prod%Mod)
if(x&1)
ans=ans*prod%Mod;
return ans;
}
LL cal(int x){
return (LL)x*(x<<1|1)%Mod6*(x+1)%Mod6/6;
}
void work(int N,LL F[]){
F[0]=1;
while(N/F[0]>S)++F[0];
++F[0];
for(int i=F[0],j,x,r;--i;){
x=N/i;
F[i]=1;
for(j=2;i*j0];++j)F[i]=(F[i]-j*j*F[i*j])%Mod;
for(;j<=x;j=r+1){
r=x/(x/j);
F[i]=(F[i]-(cal(r)-cal(j-1))%Mod*inis[x/j])%Mod;
}
}
//for(int i=1;i0];++i)cout<<"F("<"/"<"="<")="<int N,M;
LL query(int x){
if(x==0)return 0;
//printf("----query(%d)-----\n",x);
int o,k,i,j,n;
if(N/(N/x)==x){
o=0;
k=N/x;
}
else{
o=1;
k=M/x;
}
LL ans=0;
//cout<" "<if(x>S){
for(i=1;i*k0];i=j+1){
j=x/(x/i);
ans=(ans+((LL)(i+j)*(j-i+1)>>1)%Mod*F[o][i*k])%Mod;
//cout<<"Get("<"):"<<((LL)(i+j)*(j-i+1)>>1)%Mod*F[o][i*k]%Mod<"");
for(;i<=x;i=j+1){
j=x/(x/i);
ans=(ans+((LL)(i+j)*(j-i+1)>>1)%Mod*inis[x/i])%Mod;
//cout<<"Get("<"):"<<((LL)(i+j)*(j-i+1)>>1)%Mod*inis[x/i]%Mod<else
for(i=1;i<=x;i=j+1){
j=x/(x/i);
ans=(ans+((LL)(i+j)*(j-i+1)>>1)%Mod*inis[x/i])%Mod;
}
//cout<<"ans="<return ans;
}
int main(){
int i,j;
inis[1]=sg[1]=1;
for(i=2;i<=50000;++i){
if(!p[i]){
prime[++prime[0]]=i;
inis[i]=-(LL)i*i%Mod;
sg[i]=1-i;
}
for(j=1;j<=prime[0]&&i*prime[j]<=50000;++j){
p[i*prime[j]]=1;
if(i%prime[j]){
inis[i*prime[j]]=inis[i]*inis[prime[j]]%Mod;
sg[i*prime[j]]=sg[i]*(1-prime[j]);
}
else{
sg[i*prime[j]]=sg[i];
break;
}
}
}
//for(i=1;i<=20;++i)printf("%d:%I64d %I64d\n",i,inis[i],sg[i]*i);
for(i=2;i<=50000;++i){
inis[i]=(inis[i]+inis[i-1])%Mod;
sg[i]=(sg[i-1]+sg[i]*i)%Mod;
}
//for(i=1;i<=105;++i)printf("%d:%I64d\n",i,sg[i]);
scanf("%d%d",&N,&M);
if(N>M)swap(N,M);
work(N,F[0]),work(M,F[1]);
LL ans=0;
if(Sfor(i=1,j=min(N/(N/i),M/(M/i));j<=S;i=j+1,j=min(N/(N/i),M/(M/i))){
ans=(ans+(sg[j]-sg[i-1])%Mod*(N/i)%Mod*(N/i+1)%Mod*(M/i)%Mod*(M/i+1))%Mod;
//cout<<"Get("<")="<<(sg[j]-sg[i-1])%Mod*(N/i)%Mod*(N/i+1)%Mod*(M/i)%Mod*(M/i+1)%Mod<for(;i<=N;i=j+1){
j=min(N/(N/i),M/(M/i));
ans=(ans+(query(j)-query(i-1))%Mod*(N/i)%Mod*(N/i+1)%Mod*(M/i)%Mod*(M/i+1))%Mod;
//cout<<"Get("<")="<<(query(j)-query(i-1))%Mod*(N/i)%Mod*(N/i+1)%Mod*(M/i)%Mod*(M/i+1)%Mod<else
for(i=1;i<=N;i=j+1){
j=min(N/(N/i),M/(M/i));
ans=(ans+(sg[j]-sg[i-1])%Mod*(N/i)%Mod*(N/i+1)%Mod*(M/i)%Mod*(M/i+1))%Mod;
//cout<<"Get("<")="<<(sg[j]-sg[i-1])%Mod*(N/i)%Mod*(N/i+1)%Mod*(M/i)%Mod*(M/i+1)<*pow(4,Mod-2)%Mod+Mod)%Mod<