给出n,m求
因为比起lcm,我们更常用到gcd,因此首先将题目转换为求gcd的形式
#include
#include
#include
#include
#include
#define SF scanf
#define PF printf
#define MAXN 10000010
int MAXPRIME;
#define MOD 20101009
using namespace std;
vector primes;
int isprime[MAXN],mu[MAXN];
long long sum[MAXN],n,m;
void prepare(){
mu[1]=1;
for(long long i=2;i<=MAXPRIME;i++){
if(isprime[i]==0){
mu[i]=-1;
primes.push_back(i);
}
for(int j=0;j*primes[j]<=MAXPRIME;j++){
isprime[i*primes[j]]=1;
if(i%primes[j]==0){
mu[i*primes[j]]=0;
break;
}
mu[i*primes[j]]=-mu[i];
}
}
for(long long i=1;i<=MAXPRIME;i++)
sum[i]=(1ll*mu[i]*i*i+sum[i-1]+MOD)%MOD;
}
long long que(long long x,long long y){
long long res=0,last;
for(long long i=1;i<=min(x,y);i=last+1){
last=min(x/(x/i),y/(y/i));
res=(res+((sum[last]-sum[i-1])%MOD*((x/i)*((x/i)+1)/2%MOD*((y/i)*((y/i)+1)/2%MOD)%MOD))%MOD+MOD)%MOD;
res%=MOD;
}
return res;
}
int main(){
//freopen("data.in","r",stdin);
//freopen("data.out","w",stdout);
SF("%lld%lld",&n,&m);
MAXPRIME=min(n,m);
prepare();
long long ans=0,last;
for(long long i=1;i<=min(n,m);i=last+1){
last=min(n/(n/i),m/(m/i));
ans=(ans+(i+last)*(last-i+1)/2%MOD*que(n/i,m/i))%MOD;
//PF("%I64d\n",ans);
}
PF("%lld",ans);
}
与上题完全相同,但改为多组数据,最多10000组
10000组数据,明显上题O(n)的复杂度是不可能的了
因此考虑优化,为了方便起见,将答案的转移试整理一下。
#include
#include
#include
#include
#include
#define SF scanf
#define PF printf
#define MAXN 10000010
#define MAXPRIME 10000000
#define MOD 100000009
using namespace std;
int mu[MAXN],isprime[MAXN];
vector<int> primes;
long long sum[MAXN];
void prepare(){
mu[1]=1;
sum[1]=1;
for(long long i=2;i<=MAXPRIME;i++){
if(isprime[i]==0){
primes.push_back(i);
mu[i]=-1;
sum[i]=-i*i+i;
}
sum[i]%=MOD;
//PF("(%I64d)\n",sum[i]);
for(int j=0;j1;
if(i%primes[j]==0){
sum[i*primes[j]]=(primes[j]*sum[i])%MOD;
break;
}
mu[i*primes[j]]=-mu[i];
sum[i*primes[j]]=(sum[i]*sum[primes[j]])%MOD;
}
}
for(int i=1;i<=MAXPRIME;i++){
sum[i]+=sum[i-1];
sum[i]%=MOD;
}
}
int t;
long long n,m;
long long s(long long x){
return ((x*(x+1))/2)%MOD;
}
int main(){
prepare();
SF("%d",&t);
while(t--){
SF("%I64d%I64d",&n,&m);
long long last=0,res=0;
for(long long i=1;i<=min(n,m);i=last+1){
last=min(n/(n/i),m/(m/i));
res+=((s(n/i)*s(m/i))%MOD*(sum[last]-sum[i-1]+MOD+MOD))%MOD;
//PF("(%lld %lld)",last,res);
res%=MOD;
}
PF("%lld\n",res);
}
}