约数问题集
一:求约数个数
a.分解质因数(一个合数可以分通过质因数分解彻底)
b.因数和(如何得来:将分解质因数的分开然后相乘共f(n)个)
int get_num(int n) { int tot=1; for(int i=2;i*i<=n;++i) { if(n%i==0) { int x=0; while(n%i==0) { n/=i; ++x; } tot*=(x+1) } } if(n>1) tot*=2;//质数 return tot; }
ll f(ll x) { ll res=0,i; for(i=1;i*i<x;++i) if(x%i==0) res+=2; if(i*i==x) ++res; return res; }
打表大法:
for(int i=1; i<maxn/2; ++i) { for(int j=1; i*j<maxn; ++j) //板子的本身为j=2,当j=2时因子不算本身 { //这里j=1的用意就是本身也算因子与下面不符 num[i*j]++; } }
for(int i=1; i<maxn/2; ++i) { for(int j=2; i*j<maxn; ++j) //j=2不算自身为因子 { num[i*j]++; } }
二:求约数和:
a.求和公式 f(n)=(p1^0+p1^1+p1^2+…p1^a1)(p2^0+p2^1+p2^2+…p2^a2)…(pk^0+pk^1+pk^2+…pk^ak)化简乘积和便可理解为什么这样便是因数和
b.等比数列化解求和公式
ll get_sum(ll n)//返回n的约数和 { ll res=1; for(ll i=2;i*i<=n;++i) { if(n%i==0) { ll x=0; while(n%i==0) { n/=i; ++x; } res*=((1-Quick_pow(i,x+1)/(1-i)));//等比数列前n项和 } } if(n>1) res*=(1+n); return res; }
无自身:
for(int i=1; i<N/2; i++) for(int j=2; j*i<N; j++) a[i*j]=a[i*j]+i;
有自身:
for(int i=1; i<maxn; ++i) { for(int j=1; i*j<maxn; ++j) //板子的本身为j=2,当j=2时因子不算本身 { a[i*j]=a[i*j]+i; } }
eg:
HUD1215-求因子和
1 #include<stdio.h> 2 #include<string.h> 3 4 const int N=500000+5; 5 int a[N]; 6 7 int main() 8 { 9 int t,b; 10 for(int i=1;i<N/2;i++) 11 for(int j=2;j*i<N;j++) 12 a[i*j]=a[i*j]+i; 13 14 scanf("%d",&t); 15 while(t--) 16 { 17 scanf("%d",&b); 18 printf("%d\n",a[b]); 19 } 20 return 0; 21 }
HDU-2521求反素数(他本身也算因子)
1 #include<cstdio> 2 #include<string.h> 3 #define LL long long 4 #define maxn 5100 5 using namespace std; 6 7 int num[maxn]; 8 int main() 9 { 10 memset(num,0,sizeof(num)); 11 for(int i=1;i<maxn;++i) 12 { 13 for(int j=1;i*j<maxn;++j)//板子的本身为j=2,当j=2时因子不算本身 14 { //这里j=2的用意就是本身也算因子。 15 num[i*j]++; 16 } 17 } 18 int n; 19 scanf("%d",&n); 20 while(n--) 21 { 22 int a,b; 23 scanf("%d%d",&a,&b); 24 int ans; 25 int MAX=0; 26 for(int i=a;i<=b;++i) 27 { 28 if(num[i]>MAX) 29 { 30 MAX=num[i]; 31 ans=i; 32 } 33 } 34 printf("%d\n",ans); 35 } 36 }
#include<bits/stdc++.h> using namespace std; int n,a,b,maxnum,maxindex; int get_num(int n){//求n的因子个数 int tot=1; for(int i=2;i*i<=n;++i){ if(n%i==0){ int x=0; while(n%i==0){ n/=i; x++; } tot*=(x+1); } } if(n>1) tot*=2; return tot; } int main(){ while(cin>>n){ while(n--){ cin>>a>>b;maxnum=0;maxindex=a; for(int i=a;i<=b;++i){ int tmp=get_num(i); if(tmp>maxnum){maxindex=i;maxnum=tmp;} } cout<<maxindex<<endl<<maxnum<<endl; } } return 0; }
#1284 : 机会渺茫(共同约数个数-即为最大公约数的因数个数)
#include<bits/stdc++.h> typedef long long ll; using namespace std; const int mod=1e9+7; ll f(ll x) { ll res=0,i; for(i=1;i*i<x;++i) if(x%i==0) res+=2; if(i*i==x) ++res; return res; } ll gcd(ll a,ll b) { ll c; while(b){ c=a%b; a=b; b=c; } return a; } int main() { ll n,m;cin>>n>>m; ll tmp1=f(n),tmp2=f(m); ll tmp3=f(gcd(n,m)); ll cnt=tmp1*tmp2; ll x=gcd(cnt,tmp3); cout<<cnt/x<<" "<<tmp3/x<<endl; return 0; }