不多讲了,详见数论函数杂讲ppt。
算法一:分块套分块。
写完才发现复杂度为O(nT),是过不了的。
但代码还是要挂的。
#pragma GCC optimize("O2")
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
#define rep(i,j,k) for(i=j;i<=k;++i)
#define per(i,j,k) for(i=j;i>=k;--i)
#define ll long long
#define pli pair<ll,int>
#define mkp make_pair
#define X first
#define Y second
#define N 5000005
#define MOD 1000000007
ll _,n,m,k,ans;
ll pri[N],cnt,mu[N],Smu[N],dk[N],Sdk[N];bool vis[N];
inline ll add(ll a,ll b){
ll c=a+b;
if(c>=MOD)c-=MOD;
return c;
}
inline ll sub(ll a,ll b){
ll c=a-b;
if(c<0)c+=MOD;
return c;
}
inline ll mul(ll a,ll b){
return a*b%MOD;
}
ll pw(ll a){
ll b=k,c=1;
for(;b;b>>=1,a=mul(a,a))
if(b&1)c=mul(c,a);
return c;
}
void shai(){
ll i,j,v,rg=N-5;
Smu[1]=mu[1]=dk[1]=Sdk[1]=1;
rep(i,2,rg){
if(!vis[i])
mu[pri[++cnt]=i]=-1,dk[i]=pw(i);
Smu[i]=add(mu[i],Smu[i-1]);
Sdk[i]=add(dk[i],Sdk[i-1]);
for(j=1;j<=cnt&&(v=pri[j]*i)<=rg;j++){
vis[v]=1;
dk[v]=mul(dk[i],dk[pri[j]]);
if(i%pri[j]==0)break;
mu[v]=-mu[i];
}
}
}
ll f(int nn,int mm){
ll i,j,rg=min(nn,mm),rtn=0;
for(i=1;i<=rg;i=j+1){
j=min(nn/(nn/i),mm/(mm/i));
rtn=add(rtn,mul(sub(Smu[j],Smu[i-1]),mul(nn/i,mm/i)));
}
return rtn;
}
int main(){
scanf("%lld%lld",&_,&k);
shai();
ll i,j,rg;
while(_--){
scanf("%lld%lld",&n,&m);
rg=min(n,m);ans=0;
for(i=1;i<=rg;i=j+1){
j=min(n/(n/i),m/(m/i));
ans=add(ans,mul(sub(Sdk[j],Sdk[i-1]),f(n/i,m/i)));
}
printf("%lld\n",ans);
}
return 0;
}
看完算法二才知道自己原来的思路是对的。。。当时看了算法一觉得自己思路错了,顿时不爽起来,把自己写的代码全删了QAQ。
再把代码挂上。
#pragma GCC optimize("O3")
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
#define rep(i,j,k) for(i=j;i<=k;++i)
#define per(i,j,k) for(i=j;i>=k;--i)
#define ll long long
#define pli pair<ll,int>
#define mkp make_pair
#define X first
#define Y second
#define N 5000005
#define MOD 1000000007
ll _,n,m,k,ans;
ll pri[N],cnt,mu[N],g[N],Sg[N];bool vis[N];
inline ll add(ll a,ll b){
ll c=a+b;
if(c>=MOD)c-=MOD;
return c;
}
inline ll sub(ll a,ll b){
ll c=a-b;
if(c<0)c+=MOD;
return c;
}
inline ll mul(ll a,ll b){
return a*b%MOD;
}
ll pw(ll a){
ll b=k,c=1;
for(;b;b>>=1,a=mul(a,a))
if(b&1)c=mul(c,a);
return c;
}
void shai(){
ll i,j,v,rg=N-5;
mu[1]=g[1]=Sg[1]=1;
rep(i,2,rg){
if(!vis[i])
mu[pri[++cnt]=i]=-1,g[i]=sub(pw(i),1);
for(j=1;j<=cnt&&(v=pri[j]*i)<=rg;j++){
vis[v]=1;
if(i%pri[j]==0){
g[v]=mul(g[i],g[pri[j]]+1);break;
}
mu[v]=-mu[i];
g[v]=mul(g[i],g[pri[j]]);
}
Sg[i]=add(Sg[i-1],g[i]);
}
}
int main(){
scanf("%lld%lld",&_,&k);
shai();
ll i,j,rg;
while(_--){
scanf("%lld%lld",&n,&m);
rg=min(n,m);ans=0;
for(i=1;i<=rg;i=j+1){
j=min(n/(n/i),m/(m/i));
ans=add(ans,mul(mul(n/i,m/i),sub(Sg[j],Sg[i-1])));
}
printf("%lld\n",ans);
}
return 0;
}