3739: DZY loves math VIII
Time Limit: 25 Sec Memory Limit: 512 MB
Submit: 318 Solved: 50
[Submit][Status][Discuss]
Description
在XYZ的dzy loves math6问世后,dzy一直觉得这道题答案太大,一点都不优美,于是他随手在外面套上一个μ。同时,他又觉得输入两个数实在太麻烦,于是题目变成了,你能解决这个问题吗?
Input
第一行一个整数T表示询问组数,接下来T行每行一个整数n。
Output
对于每一个询问输出一行表示答案
Sample Input
1
2
Sample Output
0
HINT
T<=10^3 n<=10^7
Source
【分析】
稍微想一下
μ
的定义,你会发现这题其实能化简…
gcd(i,j)>1的情况下
μ
一定为0,质因子一定有平方…
所以直接考虑
i,j
互质的情况,即
gcd(i,j)=1
所以原式为
∑ n i=1 ∑ i j=1 μ(ij)
然后繁衍繁衍,乱搞一发,暴搜+nlogn=O(能过)
所以这题就是考你怎么求一个鬼畜的式子还不TLE
【代码】
//bzoj 3739 DZY loves math VIII
#include<cstdio>
#include<cstring>
#include<iostream>
#define N 10000000
#define ll long long
#define fo(i,j,k) for(i=j;i<=k;i++)
using namespace std;
const int mxn=10000005;
int n,m,T,cnt;
int vis[mxn],pri[mxn],miu[mxn],sum[mxn],f[mxn],a[mxn];
inline int read()
{
int x=0;char ch=getchar();
while(ch<'0'||ch>'9') ch=getchar();
while(ch>='0'&&ch<='9') x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
return x;
}
inline void init()
{
int i,j;
miu[1]=1;
fo(i,2,N)
{
if(!vis[i]) vis[i]=pri[++pri[0]]=i,miu[i]=-1;
for(j=1;j<=pri[0] && (ll)i*pri[j]<=N;j++)
{
vis[i*pri[j]]=pri[j];
if(i%pri[j]==0) break;
miu[i*pri[j]]=-miu[i];
}
}
}
inline int dfs(int k,int x,int v)
{
if(k>cnt)
{
f[x]+=v;return miu[x]*f[x];
}
return dfs(k+1,x*a[k],v)+dfs(k+1,x,v);
}
int main()
{
init();
int i,j;
fo(i,1,N)
{
sum[i]+=sum[i-1];
if(miu[i])
{
cnt=0;
for(int x=i;x>1;x/=vis[x])
a[++cnt]=vis[x];
sum[i]+=miu[i]*dfs(1,1,miu[i]);
}
}
T=read();
while(T--)
{
n=read();
printf("%d\n",sum[n]);
}
return 0;
}