題目
解法:莫比烏斯反演
一道較簡單的莫比烏斯反演,推推式子就OK了。
單次詢問時間複雜度: ,一眼看過去,誒,能過,突然就看到了多組數據 。。涼了呀
發現式中有迭代變量的乘積,於是設 ,就有:
在篩出素數後,迭代求出 的前綴和,
即可使用分塊求解。
時間複雜度:
AC代碼
#include<iostream>
#include<cstdio>
#include<vector>
using namespace std;
const int N=10000000;
vector<int> prime;
bool check[10000001];
int T,n,m;
long long summu[10000001],mu[10000001];
void sieve(){
mu[1]=1ll;
for(int i=2;i<=N;++i){
if(!check[i])prime.push_back(i),mu[i]=-1ll;
for(int j:prime){
if(i*j>N)break;
mu[i*j]=-mu[i],check[i*j]=true;
if(i%j==0){mu[i*j]=0;break;}
}
}
for(int i:prime)for(int j=1;i*j<=N;++j)summu[i*j]+=mu[j];
for(int i=1;i<=N;++i)summu[i]+=summu[i-1];
}
void solve(int n,int m){
if(n>m)swap(n,m);
int lst;long long res=0ll;
for(int i=1;i<=n;i=lst+1)lst=min(n/(n/i),m/(m/i)),res+=(summu[lst]-summu[i-1])*(n/i)*(m/i);
printf("%lld\n",res);
}
int main(){
sieve();
scanf("%d",&T);for(int i=1;i<=T;++i)scanf("%d%d",&n,&m),solve(n,m);
}