Description
Input
一共T+1行
第1行为数据组数T(T<=10)
第2~T+1行每行一个非负整数N,代表一组询问
Output
一共T行,每行两个用空格分隔的数ans1,ans2
Sample Input
6
1
2
8
13
30
2333
Sample Output
1 1
2 0
22 -2
58 -3
278 -3
1655470 2
题解
Orz YZH
杜教筛
http://blog.csdn.net/yzhyzhyzh3/article/details/78731507
YZH真是太强了!!!
代码
#include<bits/stdc++.h>
#define ll long long
#define inf 1000000000
#define pa pair<ll,ll>
using namespace std;
const int mod=1000000007;
const int N=2500005;
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
ll miu[N],phi[N];
int n,p[N],tot;
map<int,ll>mp_phi,mp_miu;
bool flag[N];
void prepration()
{
miu[1]=1LL;phi[1]=1LL;
for (int i=2;i<N;i++)
{
if (!flag[i]){p[++tot]=i;phi[i]=i-1;miu[i]=-1;}
for (int j=1;j<=tot&&p[j]*i<N;j++)
{
flag[i*p[j]]=1;
if (i%p[j]==0){phi[i*p[j]]=phi[i]*p[j];miu[i*p[j]]=0;break;}
phi[i*p[j]]=phi[i]*(p[j]-1);miu[i*p[j]]=-miu[i];
}
}
for (int i=2;i<N;i++) miu[i]+=miu[i-1],phi[i]+=phi[i-1];
}
inline ll calphi(int n)
{
if (n<N) return phi[n];
if (mp_phi[n]) return mp_phi[n];
ll ans=((ll)n+1LL)*n>>1,pos=0;
for (ll i=2;i<=n;i=pos+1)
{
pos=n/(n/i);
ans-=calphi(n/i)*(pos-i+1);
}
mp_phi[n]=ans;
return ans;
}
inline ll calmiu(int n)
{
if (n<N) return miu[n];
if (mp_miu[n]) return mp_miu[n];
ll ans=1LL,pos=0;
for (ll i=2;i<=n;i=pos+1)
{
pos=n/(n/i);
ans-=calmiu(n/i)*(pos-i+1);
}
mp_miu[n]=ans;
return ans;
}
inline void solve()
{
n=read();
printf("%lld %lld\n",calphi(n),calmiu(n));
}
int main()
{
prepration();
int Case=read();
while (Case--) solve();
return 0;
}