《数论及应用》第6章 乘性函数问题(上)
来源:互联网 发布:js复制对象副本 编辑:程序博客网 时间:2024/06/05 09:10
1.欧拉函数:
关于欧拉函数,求的是指不超过n的与n互素的正整数的个数,按一般思想就是对数n进行素因子分解之后,所有的素数幂的欧拉函数之积
定理:设p是一个素数,a是正整数,那么 φ (p^a)=p^a-p^(a-1)
推论:若n是奇数,φ(2n)=φ(n)
两个常用定理:
欧拉定理:对任何两个互质的正整数a,m(m>=2)有a^φ(m)≡1(mod m)
费马小定理:当m是质数的时候,a^(m-1)≡1(mod m)
欧拉函数的算法实现:
//递归求欧拉#include <stdio.h>#define maxn 10000int phi[maxn];//个人觉得这个时间比较慢,//而且你懂的,数组的大小是有限的,//如果是求大数的就不行了void Phi(){ for(int i=1;i<=maxn;i++) phi[i]=i; for(int i=2;i<=maxn;i+=2) phi[i]/=2; for(int i=3;i<=maxn;i+=2) if(phi[i]==i) for(int j=i;j<=maxn;j+=i) phi[j]=phi[j]/i*(i-1);}
然后是一种单独求欧拉值的:
//单独求欧拉函数#include <stdio.h>#include <math.h>//如果必要,可以改成long longunsigned euler(unsigned x){ unsigned i,res=x; for(i=2;i<=sqrt(x*1.0);i++) if(x%i==0) { res=res/i*(i-1); while(x%i==0) x/=i; } if(x>1) res=res/x*(x-1); return res;}
还有一种素数表实现欧拉值的写法:
//传说这貌似时间最少//用是时间是O(n) n是sqrt(x)内的素数的个数//写起来好像跟前面的没什么很大的区别#include <stdio.h>#include <string.h>int prime[50000];int p[20000];void Prime(){ memset(prime,1,sizeof(prime)); prime[0]=prime[1]=0; for(int i=2;i*i<=50000;i++) if(prime[i]) for(int j=2*i;j<=50000;j+=i) prime[j]=0; int k=0; for(int i=0;i<=50000;i++) { if(prime[i]) p[++k]=i; }}int phi(int n){ int res=n; for(int i=1;p[i]*p[i]<=n;i++) if(n%p[i]==0) { res=res-res/p[i]; do n/=p[i]; while(n%p[i]==0); } if(n>1) res=res-res/n; return res;}
欧拉函数的应用:
http://poj.org/problem?id=2407
就是模板题,直接求出欧拉值
水题
#include <stdio.h>long long euler(long long x){ long long i,res=x; for(i=2;i*i<=x;i++) if(x%i==0) { res=res/i*(i-1); while(x%i==0) x/=i; } if(x>1) res=res/x*(x-1); return res;}int main(){ long long n; while(scanf("%I64d",&n)!=EOF,n) { printf("%I64d\n",euler(n)); } return 0;}
http://poj.org/problem?id=1284
求原根
所谓原根指的是http://zh.wikipedia.org/wiki/原根 反正是不好玩的东西
#include <stdio.h>int euler(int x){ int i,res=x; for(i=2;i*i<=x;i++) { if(x%i==0) { res=res/i*(i-1); while(x%i==0) x/=i; } } if(x>1) res=res/x*(x-1); return res;}int main(){ int n; while(scanf("%d",&n)!=EOF) { printf("%d\n",euler(n-1)); } return 0;}
http://poj.org/problem?id=2478
还是欧拉函数的应用,求的是从2到n的欧拉值之和
这个题REWA TLE MLE 多次。。。RE是因为没有注意到数据类型,数组开大了就MLE了,然后换了筛素数的方法求欧拉值结果WA了,改对之后又是RE了 唉 伤不起啊 给一个水题坑死了
算了 坑就坑吧 把试过的几次代码都贴上
//这个时间用了235ms#include <cstdlib>#include <iostream>using namespace std;#define maxn 1000001long long a[maxn];int main(){ long long i,j; for(i=1;i<=maxn;i++) a[i]=i; for(i=2;i<=maxn;i+=2) a[i]/=2; for(i=3;i<=maxn;i+=2) if(a[i]==i) { for(j=i;j<=maxn;j+=i) a[j]=a[j]/i*(i-1); } for(i=3;i<maxn;i++) a[i]+=a[i-1]; long long n; while(cin>>n&&n) cout<<a[n]<<endl; return 0;}
//这个时间用了79ms#include <iostream>#include <cstdio>using namespace std;#define maxn 1000001bool isprime[maxn];long long prime[maxn];long long phi[maxn];long long ans[maxn];void getprime(){ long long k=0; for(int i=0;i<=maxn;i++) isprime[i]=1; for(int i=2;i<=maxn;i++) { if(isprime[i]) { prime[k++]=i; phi[i]=i-1; } for(int j=0;j<k&′[j]*i<=maxn;j++) { isprime[i*prime[j]]=0; if(i%prime[j]!=0) { phi[i*prime[j]]=phi[i]*phi[prime[j]]; } else { phi[i*prime[j]]=phi[i]*prime[j]; break; } } }}int main(){ getprime(); ans[1]=0; for(int i=2;i<=maxn;i++) ans[i]=ans[i-1]+phi[i]; int n; while(scanf("%d",&n),n) { printf("%I64d\n",ans[n]); } return 0;}
//这个用了94ms#include <iostream>#include <cstdio>using namespace std;#define maxn 1000001bool isprime[maxn];long long prime[maxn];long long phi[maxn];long long ans[maxn];void getprime(){ long long k=0; for(int i=0;i<=maxn;i++) isprime[i]=1; for(int i=2;i<=maxn;i++) { if(isprime[i]) { prime[k++]=i; phi[i]=i-1; } for(int j=0;j<k&′[j]*i<=maxn;j++) { isprime[i*prime[j]]=0; if(i%prime[j]!=0) { phi[i*prime[j]]=phi[i]*phi[prime[j]]; } else { phi[i*prime[j]]=phi[i]*prime[j]; break; } } }}int main(){ getprime(); ans[1]=0; for(int i=2;i<=maxn;i++) ans[i]=ans[i-1]+phi[i]; int n; while(scanf("%d",&n),n) { printf("%I64d\n",ans[n]); } return 0;}
http://poj.org/problem?id=3090
根据理解将平面划分为两个区域,中间那一线的当然只看得到最近的点(1,1) 至于其他的就只看得到,与输入的n值所互质的数的个数,总的意思还是求1到n的欧拉值之和
#include <stdio.h>#define maxn 10000int phi[maxn];int main(){ for(int i=1;i<=maxn;i++) phi[i]=i; for(int i=2;i<=maxn;i+=2) phi[i]/=2; for(int i=3;i<=maxn;i+=2) { if(phi[i]==i) { for(int j=i;j<=maxn;j+=i) phi[j]=phi[j]/i*(i-1); } } for(int i=2;i<=maxn;i++) phi[i]+=phi[i-1]; int n,t; scanf("%d",&t); int tt=0; while(t--) { scanf("%d",&n); printf("%d %d %d\n",++tt,n,2*phi[n]+1); } return 0;}
- 《数论及应用》第6章 乘性函数问题(上)
- 《数论及应用》第2章 素数问题
- 《数论及应用》第3章 同余问题
- 《数论及应用》第1章 数的整除性问题
- 第3章 动态规划 矩阵连乘问题
- 第3章 动态规划 矩阵连乘问题
- ACM数论模板及应用
- 解析数论引论 第2章 数论函数和狄利克雷乘积
- Windows上PIL安装及应用问题
- 51Nod_P1239 欧拉函数之和(数论+杜教筛+欧拉函数+哈希+快速乘)
- GAE 时区问题及模板函数应用
- ACM 大数问题函数及应用
- 数论及应用之总结提纲
- 数论基本定理及应用(二)
- 数论基本定理及应用(三)
- 数论基本定理及应用(四)
- 浅谈简单数论及应用(一)
- 【jzoj4668】【腐败】【数论】【快速乘】
- 剖析web服务原理--简单的Web服务器模拟
- 开发Struts 2项目遇到的一个问题,就是在struts-tags标签库下没有了s:datetimepicker标签的解决办法
- Javascript+PHP实现在线拍照功能
- 5. Probabilistic Analysis and Randomized Algorithms——Introduction to Algorithms Third Edition
- 约瑟夫环问题(Josephus)
- 《数论及应用》第6章 乘性函数问题(上)
- 铁道部新客票系统设计(一)
- Struts2中的ActionContext
- UDA1341声卡驱动 madplay 播放
- 铁道部新客票系统设计(二)
- javascript小知识
- Thinkphp常用系统配置大全
- JS原生方法实现JQuery ready()方法
- Object-c学习点滴——使用NSMutableArray犯的一个低级错误!!