第三次复习反演。。。
感觉第二次学的时候还是有点用的
整理了下思路。可以去看一下我的blog
这题就是第二种类型的题。然而我不会化简K。。%PoPoQQQ
#include<cstdio> #include<iostream> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> using namespace std; typedef long long LL; bool v[10001000]; int pr,prime[10001000]; int K[10001000],p[10001000],a[10001000];//最后一个质因数^其次数,该质因数次数 void get_K() { memset(v,true,sizeof(v)); v[1]=false; for(int i=2;i<=10000000;i++) { if(v[i]==true) { prime[++pr]=i; p[i]=i; a[i]=1; K[i]=1; } for(int j=1;j<=pr&&(LL(i*prime[j]))<=10000000;j++) { v[i*prime[j]]=false; if(i%prime[j]==0) { p[i*prime[j]]=p[i]*prime[j]; a[i*prime[j]]=a[i]+1; int t=i/p[i]; if(t==1)K[i*prime[j]]=1; else K[i*prime[j]]=(a[t]==a[i*prime[j]]?-K[t]:0); break; } p[i*prime[j]]=prime[j]; a[i*prime[j]]=1; K[i*prime[j]]=(a[i]==a[i*prime[j]])?(-K[i]):0; } } for(int i=1;i<=10000000;i++)K[i]+=K[i-1]; } int main() { get_K(); int T_T; scanf("%d",&T_T); while(T_T--) { int n,m; scanf("%d%d",&n,&m); LL ans=0,last; for(int T=1;T<=min(n,m);T=last+1) { last=min(n/(n/T),m/(m/T)); ans+=(LL(n/T))*(LL(m/T))*(LL(K[last]-K[T-1])); } printf("%lld ",ans); } return 0; }