分析:
http://blog.csdn.net/acdreamers/article/details/12871643
分析参见这一篇
http://wenku.baidu.com/view/fbe263d384254b35eefd34eb.html
分块看这一篇
#include<cstdio> #include<cstring> #include<queue> #include<cstdlib> #include<algorithm> #include<vector> #include<cmath> using namespace std; typedef long long LL; const int N=5e5+5; const int INF=0x3f3f3f3f; bool vis[N]; int prime[N],mu[N]; void getmu() { mu[1] = 1; int cnt = 0; for(int i=2; i<=N-5; i++) { if(!vis[i]) { prime[cnt++] = i; mu[i] = -1; } for(int j=0; j<cnt&&i*prime[j]<=N-5; j++) { vis[i*prime[j]] = 1; if(i%prime[j]) mu[i*prime[j]] = -mu[i]; else { mu[i*prime[j]] = 0; break; } } } } int cal(int n,int x){ int res=0; do{ ++res; n/=x; }while(n%x==0); return res; } int num[N]; int F[N][20],T,n,m,p; int main(){ getmu(); for(int i=2;i<=N-5;++i) if(!num[i]) for(int j=i;j<=N-5;j+=i) num[j]+=cal(j,i); for(int i=1;i<=N-5;++i) for(int j=i;j<=N-5;j+=i) F[j][num[i]]+=mu[j/i]; for(int i=1;i<=N-5;++i) for(int j=1;j<19;++j) F[i][j]+=F[i][j-1]; for(int i=1;i<=N-5;++i) for(int j=0;j<19;++j) F[i][j]+=F[i-1][j]; scanf("%d",&T); while(T--){ scanf("%d%d%d",&n,&m,&p); LL ans=0; if(p>=19){ printf("%I64d\n",1ll*n*m); continue; } if(n>m)swap(n,m); for(int i=1,j;i<=n;i=j+1){ j=min(n/(n/i),m/(m/i)); ans+=(1ll*F[j][p]-F[i-1][p])*(n/i)*(m/i); } printf("%I64d\n",ans); } return 0; }
时间: 2024-10-13 15:15:32