关于数论

来源:互联网 发布:吾知子之所以距我的之 编辑:程序博客网 时间:2024/05/18 00:20

终于下定决心好好搞搞数论了

首先这里的题解法全部故意避开莫比乌斯反演

bzoj2810:

入门级,先线筛欧拉

sum[1]=1;for(ll i=1;i<=n;i++)phi[i]=i;for(ll i=2;i<=n;i++){if(phi[i]==i){for(ll j=i;j<=n;j+=i){phi[j]=phi[j]/i*(i-1);}}sum[i]=sum[i-1]+phi[i];}
然后有一个结论:

求gcd(i,j)=x 1<=i,j<=n 的对数等于求gcd(i,j)=1 1<=i,j<=n/x的对数

对欧拉函数求前缀和,枚举;

//Copyright(c)2015 liuchenrui#include<cstdio>#include<ctime>#include<iostream>#include<algorithm>#include<cstring>#define ll long longusing namespace std;inline void splay(ll &v){v=0;char c=0;ll p=1;while(c<'0' || c>'9'){if(c=='-')p=-1;c=getchar();}while(c>='0' && c<='9'){v=(v<<3)+(v<<1)+c-'0';c=getchar();}v*=p;}ll phi[10000010];ll sum[10000010];ll ans;ll get(ll num){return (sum[num]<<1)-1;}int main(){freopen("xxx.in","r",stdin);freopen("xxx.out","w",stdout);ll n;splay(n);sum[1]=1;for(ll i=1;i<=n;i++)phi[i]=i;for(ll i=2;i<=n;i++){if(phi[i]==i){for(ll j=i;j<=n;j+=i){phi[j]=phi[j]/i*(i-1);}}sum[i]=sum[i-1]+phi[i];}for(ll i=2;i<=n;i++){if(phi[i]==i-1){ans+=get(n/i);}}cout<<ans<<endl;}

bzoj 2190

同理 对欧拉函数求前缀和,枚举;

答案:sigma(phi[i])*2-1+2 (i<n)

//Copyright(c)2015 liuchenrui#include<cstdio>#include<ctime>#include<iostream>#include<algorithm>#include<cstring>#define ll long longusing namespace std;inline void splay(ll &v){v=0;char c=0;ll p=1;while(c<'0' || c>'9'){if(c=='-')p=-1;c=getchar();}while(c>='0' && c<='9'){v=(v<<3)+(v<<1)+c-'0';c=getchar();}v*=p;}ll phi[10000010];ll sum[10000010];ll ans;int main(){freopen("xxx.in","r",stdin);freopen("xxx.out","w",stdout);ll n;splay(n);sum[1]=1;for(ll i=1;i<=n;i++)phi[i]=i;for(ll i=2;i<=n;i++){if(phi[i]==i){for(ll j=i;j<=n;j+=i){phi[j]=phi[j]/i*(i-1);}}sum[i]=sum[i-1]+phi[i];}for(ll i=1;i<n;i++){ans+=phi[i];}cout<<ans*2+1<<endl;}

bzoj 2005

这道题。。看了一个小时才看懂

首先我们要得出 f[i]为gcd(x,y)=i的对数

那么我们可以发现 f[i]=取下整(n/i)*(m/i)-f[i*2]-f[i*3]-f[i*4].....

那么倒着求f[i]就好了

我卡在了最后统计方案数上

对于每一个数对(x,y),令gcd(x,y)==t

那么它会对答案产生(i-1)*2+1的贡献

为什么?我们想想gcd的意义:从(0,0)开始走向(x,y)所经过的整点数-1

那么根据题意我们可以发现贡献为(i-1)*2+1

//Copyright(c)2015 liuchenrui#include<cstdio>#include<ctime>#include<iostream>#include<algorithm>#include<cstring>#define ll long longusing namespace std;ll f[100010];ll n,m;int main(){freopen("xxx.in","r",stdin);freopen("xxx.out","w",stdout);cin>>n>>m;ll ans=0;for(ll i=min(n,m);i>=1;i--){f[i]=(n/i)*(m/i);for(ll j=i<<1;j<=min(n,m);j+=i)f[i]-=f[j];ans+=(f[i]*(2*i-1));}cout<<ans<<endl;}

bzoj

0 0
原创粉丝点击