链接:戳这里
思路:一开始肯定是想暴力枚举质数p,然后n/p m/p 再加上分块去搞 明显还是会超时
超时代码:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<string> #include<vector> #include <ctime> #include<queue> #include<set> #include<map> #include<stack> #include<iomanip> #include<cmath> #define mst(ss,b) memset((ss),(b),sizeof(ss)) #define maxn 0x3f3f3f3f #define MAX 10000000 ///#pragma comment(linker, "/STACK:102400000,102400000") typedef long long ll; typedef unsigned long long ull; #define INF (1ll<<60)-1 using namespace std; int mu[MAX],prime[MAX],vis[MAX],sum[MAX]; int cnt; void Moblus(){ cnt=0; mst(vis,0); sum[1]=mu[1]=1; sum[0]=0; for(int i=2;i<=MAX;i++){ if(!vis[i]){ prime[++cnt]=i; mu[i]=-1; } for(int j=1;j<=cnt;j++){ if(i*prime[j]>MAX) break; vis[i*prime[j]]=1; if(i%prime[j]==0){ mu[i*prime[j]]=0; break; } else mu[i*prime[j]]=-mu[i]; } sum[i]=sum[i-1]+mu[i]; } } int main(){ Moblus(); int T,n,m; scanf("%d",&T); while(T--){ scanf("%d%d",&n,&m); if(n>m) swap(n,m); ll ans=0; for(int i=1;i<=cnt && prime[i]<=n;i++){ int nn=n/prime[i],mm=m/prime[i]; int last=0; for(int j=1;j<=nn;j=last+1){ last=min(nn/(nn/j),(mm/(mm/j))); ans+=(ll)(nn/j)*(mm/j)*(sum[last]-sum[j-1]); } } printf("%lld\n",ans); } return 0; }
然后去找了一篇博客,说的很清楚啊,我截图一下吧
复杂度的话大概在O(T*logN) 仰慕黄学长
代码:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<string> #include<vector> #include <ctime> #include<queue> #include<set> #include<map> #include<stack> #include<iomanip> #include<cmath> #define mst(ss,b) memset((ss),(b),sizeof(ss)) #define maxn 0x3f3f3f3f #define MAX 10000001 ///#pragma comment(linker, "/STACK:102400000,102400000") typedef long long ll; typedef unsigned long long ull; #define INF (1ll<<60)-1 using namespace std; int mu[MAX],prime[MAX],vis[MAX]; ll g[MAX]; int cnt; void Moblus(){ cnt=0; mst(vis,0); mu[1]=1; for(int i=2;i<=MAX;i++){ if(!vis[i]){ prime[++cnt]=i; mu[i]=-1; } for(int j=1;j<=cnt;j++){ if(i*prime[j]>MAX) break; vis[i*prime[j]]=1; if(i%prime[j]==0){ mu[i*prime[j]]=0; break; } else mu[i*prime[j]]=-mu[i]; } } for(int i=1;i<=cnt;i++){ int p=prime[i]; for(int j=1;j*p<=MAX;j++){ g[j*p]+=mu[j]; } } for(int i=1;i<=MAX;i++) g[i]+=g[i-1]; } int main(){ Moblus(); int T,n,m; scanf("%d",&T); while(T--){ scanf("%d%d",&n,&m); if(n>m) swap(n,m); ll ans=0; for(int i=1,last=0;i<=n;i=last+1){ last=min((n/(n/i)),(m/(m/i))); ans+=(ll)(g[last]-g[i-1])*(n/i)*(m/i); } printf("%lld\n",ans); } return 0; }