BZOJ_P3944 Sum(数论+杜教筛)

来源:互联网 发布:windows app文件夹 编辑:程序博客网 时间:2024/05/16 10:09

BZOJ传送门

Time Limit: 10 Sec Memory Limit: 128 MB
Submit: 1108 Solved: 270
[Submit][Status][Discuss]
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

HINT

Source

跟前面两道题一样!
循环变量要开long long !!!!!!!!!
long long/(long long/int)会计算错误!!!!
你在逗我!!!!!!
下面那个是拿哈希表写的

#include<cstdio>#include<cstring>#define N 2000000#define M 100005inline long long in(long long x=0,char ch=getchar()){while(ch>'9'||ch<'0') ch=getchar();    while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();return x;}int cnt,t;int pr[N+10],mu[N+10];long long phi[N+10];long long n;long long p[M];int q[M];bool v[M];void Pre(){    mu[1]=phi[1]=1;    for(int i=2;i<=N;i++){        if(!phi[i]) pr[++cnt]=i,mu[i]=-1,phi[i]=i-1;        for(int j=1;j<=cnt&&i*pr[j]<=N;j++){            if(!(i%pr[j])){phi[i*pr[j]]=phi[i]*pr[j];break;}            mu[i*pr[j]]=-mu[i];phi[i*pr[j]]=phi[i]*(pr[j]-1);        }    }    for(int i=2;i<=N;i++) mu[i]+=mu[i-1],phi[i]+=phi[i-1];}inline long long getphi(int x){return x<=N?phi[x]:p[n/x];}inline int getmu(int x){return x<=N?mu[x]:q[n/x];}inline void calc(long long x){    if(x<=N) return;long long t=n/x;    if(v[t]) return;v[t]=1;    p[t]=(x*(x+1))>>1;q[t]=1;    for(long long i=2,j;i<=x;i=j+1){        j=x/(x/i);calc(x/i);        p[t]-=getphi(x/i)*(j-i+1);q[t]-=getmu(x/i)*(j-i+1);    }}int main(){    Pre();t=in();    while(t--){        memset(v,0,sizeof(v));n=in();        if(n<=N) printf("%lld ",phi[n]),printf("%d\n",mu[n]);        else calc(n),printf("%lld ",p[1]),printf("%d\n",q[1]);    }    return 0;}
#include<cstdio>#include<cstring>#define N 1000000#define Mod 2333333inline int in(int x=0,char ch=getchar()){while(ch>'9'||ch<'0') ch=getchar();    while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();return x;}int cnt,t,sum;int pr[N+10],mu[N+10];long long phi[N+10];long long n;struct ANS{    int a;long long b;    ANS operator - (const ANS &x)const {return (ANS){a-x.a,b-x.b};}    ANS operator * (const int x)const {return (ANS){a*x,b*x};}}ans;struct map{long long k,nxt;ANS v;}hash[Mod];int head[Mod];void Pre(){    mu[1]=phi[1]=1;    for(int i=2;i<=N;i++){        if(!phi[i]) pr[++cnt]=i,mu[i]=-1,phi[i]=i-1;        for(int j=1;j<=cnt&&i*pr[j]<=N;j++){            if(!(i%pr[j])){phi[i*pr[j]]=phi[i]*pr[j];break;}            mu[i*pr[j]]=-mu[i];phi[i*pr[j]]=phi[i]*(pr[j]-1);        }    }    for(int i=2;i<=N;i++) mu[i]+=mu[i-1],phi[i]+=phi[i-1];}inline void add(long long k,ANS a){    int ha=k%Mod;hash[++sum].k=k,hash[sum].v=a,hash[sum].nxt=head[ha],head[ha]=sum;}inline ANS calc(long long x){    if(x<=N) return (ANS){mu[x],phi[x]};int ha=x%Mod;    for(int i=head[ha];i;i=hash[i].nxt) if(hash[i].k==x) return hash[i].v;    ANS res;res.a=1,res.b=(x*(x+1))>>1;    for(long long i=2,j;i<=x;i=j+1){        j=x/(x/i);res=res-calc(x/i)*(j-i+1);    }    add(x,res);return res;}int main(){    Pre();t=in();    while(t--){        n=in();ans=calc(n);        printf("%lld ",ans.b);printf("%d\n",ans.a);    }    return 0;}
1 0
原创粉丝点击