数论中的基本算法 POJ 1845 SPOJ DIVSUM
2012-08-20 15:24
411 查看
求一个数n的所有约数复杂度sqrt(n),i从1枚举到sqrt(n),如果n%i==0,那么i和n/i都是n的约数
扩展欧几里得 求逆元(只要a与b互素,那么就有逆元)
O(n)打素数表
O(nlogn)打素数表
POJ 1845 二分(1+x+x^2...+x^n)求和
SPOJ DIVSUM
SPOJ DIVSUM 另一种做法
扩展欧几里得 求逆元(只要a与b互素,那么就有逆元)
#include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #define mod 9973 typedef long long ll; void ExGcd(int a,int b,int &x,int &y){ if(b==0){ x=1; y=0; return ; } ExGcd(b,a%b,x,y); int t=x; x=y; y=t-a/b*y; } int main(){ int t,T,rev,x; int a,b; scanf("%d",&T); for(t=1;t<=T;t++){ scanf("%d %d",&a,&b); ExGcd(b,mod,rev,x); printf("%d\n",((rev*a)%mod+mod)%mod); } }
O(n)打素数表
int pn = 0,prime[MAXN],factor[MAXN];//factor[i]为i的最小素约数 void get_prime(int n){ int i,j; for(i=1;i<=n;i++) factor[i]=i; for(i=2;i<=n;i++){ if(i==factor[i])prime[pn++]=i; for(j=0;j<pn && prime[j]*i<=n;j++){ factor[i*prime[j]]=prime[j]; if(i%prime[j]==0) break; } } }
O(nlogn)打素数表
void get_prime(){ int n; int i,j; for(i=2;i<=sqrt(n)+1;i++){ if(!yes[i]) for(j=i*i;j<=n;j+=i) yes[j]=1; } }
POJ 1845 二分(1+x+x^2...+x^n)求和
#include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #define mod 9901 typedef long long ll; const int MAXN=10000; int a,b,k; int p[MAXN],n[MAXN]; ll quick(ll num,ll mi){ ll ans=1; while(mi){ if(mi%2)ans=(ans*num)%mod; num=(num*num)%mod; mi/=2; } return ans%mod; } ll sum(ll num,ll mi){ if(mi==0)return 1; if(mi%2) return (sum(num,mi/2)*(1+quick(num,mi/2+1)))%mod; return (sum(num,mi/2-1)*(1+quick(num,mi/2+1))+quick(num,mi/2))%mod; } void factor(int a){ int i; k=0; for(i=2;i*i<=a;){ //sqrt(n)的复杂度分解整数 if(a%i==0){ p[k]=i; n[k]=0; while(a%i==0){ n[k]++; a/=i; } k++; } if(i>2)i+=2; else i++; } if(a>1){ p[k]=a; n[k]=1; k++; } } int main(){ int i; scanf("%d %d",&a,&b); factor(a); int ans=1; for(i=0;i<k;i++) ans=(ans*(sum(p[i],n[i]*b))%mod)%mod; printf("%d\n",ans); }POJ 1845 逆元的方法
#include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #define mod 9901 typedef long long ll; const int MAXN=10000; int a,b,k; int p[MAXN],n[MAXN]; void ExGcd(int a,int b,int &x,int &y){ if(b==0){ x=1; y=0; return ; } ExGcd(b,a%b,x,y); int t=x; x=y; y=t-a/b*y; } int reverse(int num){ int rev,x; ExGcd(num,mod,rev,x); return rev; } ll quick(ll num,ll mi){ ll ans=1; while(mi){ if(mi%2)ans=(ans*num)%mod; num=(num*num)%mod; mi/=2; } return ans%mod; } ll sum(ll num,ll mi){ if(num%mod==1) //注意到这种情况不能用逆元,因为num-1与mod不互素 return (mi+1)%mod; return (((quick(num,mi+1)-1+mod)%mod)*reverse((num-1)%mod)%mod+mod)%mod; } void factor(int a){ int i; k=0; for(i=2;i*i<=a;){ //sqrt(n)的复杂度分解整数 if(a%i==0){ p[k]=i; n[k]=0; while(a%i==0){ n[k]++; a/=i; } k++; } if(i>2)i+=2; else i++; } if(a>1){ p[k]=a; n[k]=1; k++; } } int main(){ int i; scanf("%d %d",&a,&b); factor(a); int ans=1; for(i=0;i<k;i++) ans=(ans*(sum(p[i],n[i]*b))%mod+mod)%mod; printf("%d\n",ans); }
SPOJ DIVSUM
#include <cstdio> #include <cstring> #include <cstdlib> #include <cmath> const int MAXN = 1501000, N = 500010; int pn = 0, prime[MAXN], factor[MAXN]; void get_prime(int n){ int i,j; for(i=1;i<=n;i++) factor[i]=i; for(i=2;i<=n;i++){ if(i==factor[i])prime[pn++]=i; for(j=0;j<pn && prime[j]*i<=n;j++){ factor[i*prime[j]]=prime[j]; if(i%prime[j]==0) break; } } } int main() { int cases; get_prime(N); scanf("%d", &cases); while(cases--) { int n, tmpn; long long ans = 1; scanf("%d", &n); tmpn = n; while (tmpn != factor[tmpn]) { long long fac = factor[tmpn], mtp = fac; while (tmpn % fac == 0) { mtp *= fac; tmpn /= fac; } ans *= (1 - mtp) / (1 - fac); } if (tmpn > 1) ans *= (1 + tmpn); ans -= n; printf("%lld\n", ans); } return 0; }
SPOJ DIVSUM 另一种做法
#include<cstdio> using namespace std; int sum[500100]; int main() { int T,t,i,j,n; scanf("%d",&T); for(i=1;i<=500000;i++){ for(j=2;i*j<=500000;j++){//若j从1开始则会算上本身 sum[i*j]+=i; } } for(t=1;t<=T;t++){ scanf("%d",&n); printf("%d\n",sum ); } }
相关文章推荐
- ACM基本算法分类、推荐学习资料和配套poj习题
- POJ 基本算法
- poj 1845 Sumdiv 数论--等比数列和(逆元或者递归)
- 初级->基本算法->构造法 poj 3295 Tautology(永真式)
- POJ 1845 sumdiv 数论 A^B 的所有约数之和
- Sumdiv POJ - 1845 (数论)
- POJ 1845-Sumdiv 数论 +快速幂&&筛素&&分解质因数&&求因数之和的模板
- POJ基本算法bfs1753,2965
- 初级->基本算法->模拟 poj 2632 Crashing Robots
- poj 1845 Sumdiv(数论+二分)
- ACM基本算法分类、推荐学习资料和配套poj习题
- POJ 1845 数论
- poj1845--Sumdiv(数论篇3--真滴是数论啊。。。。)
- poj 数论 1845
- poj 1845 Sumdiv——数论
- POJ 1845-Sumdiv(数论,A^B的所有约数和)
- 数论poj1845(A^B的约数和)
- poj——1845(数论之因子的和)
- poj1845——Sumdiv(数论+幂的因子和)
- POJ 1845 数论