转载请注明出处,谢谢http://blog.csdn.net/bigtiao097?viewmode=contents
求欧拉函数和莫比乌斯函数的前缀和,数据范围 231−1
这个题就是之前做过的51Nod 1239(求欧拉函数前缀和) 和 51Nod 1244(求莫比乌斯函数前缀和)合起来
这两个题的题解分别在这里和这里
个人还是很喜欢51Nod这样的oj,会每组数据都分别给运行时间,也可以获得数据,感觉bzoj给的运行时间很迷。。
具体代码如下:
Result:Accepted Memory:29952 KB Time :1687 ms
#include
const int maxn = 5e6;//maxn = n^(2/3)
using namespace std;
typedef long long ll;
const int HASH_MOD=2e5;
int mu[maxn];
bool vis[maxn];
int p[maxn];
ll phi[maxn];
ll n;
struct Hash{
ll key[HASH_MOD], val[HASH_MOD];
int head[HASH_MOD], nxt[HASH_MOD];
int tot;
void init(){
memset(head, -1, sizeof(head));
tot = 0;
}
ll inst(ll x, ll y){
int k = x % HASH_MOD;
key[tot] = x;
val[tot] = y;
nxt[tot] = head[k];
head[k] = tot++;
}
ll finda(ll x){
int k = x % HASH_MOD;
for(int i = head[k]; i != -1; i = nxt[i])
if(key[i] == x)
return val[i];
return -1;
}
}hs,hs2;
void Linear_Shaker()
{
phi[1]=1;mu[1]=1;
for(int i=2;iif(!vis[i])
{
phi[i]=i-1;
mu[i]=-1;
p[++p[0]]=i;
}
for(int j=1;p[j]*i1;
if(i%p[j]==0)
{
phi[p[j]*i]=phi[i]*p[j];
mu[p[j]*i]=0;
break;
}
phi[p[j]*i]=phi[i]*(p[j]-1);
mu[p[j]*i]=-mu[i];
}
}
for(int i=1;i1];
mu[i]+=mu[i-1];
}
}
ll calcmu(ll x)
{
if (xreturn mu[x];
int y = hs.finda(x);
if(y!= -1)
return y;
ll ans = 1;
for(ll l=2,r; l<=x; l=r+1)
{
r=x/(x/l);
ans-=calcmu(x/l)*(r-l+1);
}
hs.inst(x,ans);
return ans;
}
ll calcphi(ll x)
{
if (xreturn phi[x];
ll y = hs2.finda(x);
if(y!= -1)
return y;
ll ans = x*(x+1)/2;
for(ll l=2,r; l<=x; l=r+1)
{
r=x/(x/l);
ans-=calcphi(x/l)*((r-l+1));
}
hs2.inst(x,ans);
return ans;
}
int main()
{
Linear_Shaker();
int T;
scanf("%d",&T);
while(T--)
{
hs.init();
hs2.init();
scanf("%lld",&n);
printf("%lld %lld\n",calcphi(n),calcmu(n));
}
return 0;
}