一行,两个正整数N和M。
N<=1000000,M<=1000000
标签:地方 pre tput mes 产生 顺序 pac inpu int
题目大意:
/************************************************************** Problem: 4807 User: 20011023 Language: C++ Result: Accepted Time:1332 ms Memory:17892 kb ****************************************************************/ #include<bits/stdc++.h> using namespace std; typedef long long ll; const int N=1000000+5; const ll mod=1e10; int n,m; int k; int exi[N]; int ans; int yue[N],has[N],cnt; int pri[N],tot; bool vis[N]; void sieve(){ for(int i=2;i<=n;i++){ if(!vis[i]){ pri[++tot]=i; } for(int j=1;j<=tot;j++){ if(pri[j]*i>n) break; vis[pri[j]*i]=1; if(i%pri[j]==0) break; } } } void div1(int x){ for(int i=1;pri[i]*pri[i]<=x;i++){ while(x%pri[i]==0){ exi[i]++; x/=pri[i]; } } if(x>1){ int k=lower_bound(pri+1,pri+tot+1,x)-pri; exi[k]++; } } int div2(int x){ int now=x; for(int i=1;pri[i]*pri[i]<=x;i++){ if(now%pri[i]==0){ while(now%pri[i]==0){ if(exi[i]){ exi[i]--; x/=pri[i];} now/=pri[i]; } } } if(now>1){ int k=lower_bound(pri+1,pri+tot+1,now)-pri; if(exi[k]){ exi[k]--; x/=pri[k]; } } return x; } struct big{ ll a[10]; int cnt; void pre(){ cnt=1,a[1]=1; } void mul(const ll &x){ int ji=0; for(int i=1;i<=cnt;i++){ a[i]=a[i]*x+ji; ji=a[i]/mod; a[i]%=mod; } if(ji){ a[++cnt]=ji; } if(cnt>5) cnt=5; } void op(){ while(a[cnt]==0&&cnt>1) cnt--; printf("%lld",a[cnt--]); while(cnt)printf("%010lld",a[cnt--]); } }A; void wrk(){ A.pre(); for(int i=m+1;i<=n;i++){ int re=div2(i); A.mul(re); } } int main() { scanf("%d%d",&n,&m); if(m>n) swap(n,m); if(n==m){ printf("1");return 0; } else if(n==1){ printf("%d",m);return 0; } else if(m==1){ printf("%d",n);return 0; } sieve(); for(int i=1;i<=n-m;i++){ div1(i); } wrk(); A.op(); return 0; }
质因数分解往往可以起到意想不到的优化,因为一个数的分解呈现了它的本质。
决定了一切的乘除,gcd,找因数等运算。
1.乘除,本质上是质因子次数的加减。
2.gcd本质上是所有质因子次数取min再相乘。lcm则取max
3.因数的产生本质上是一个乘法原理。质因子次数的选择也决定了因数的数值。
并且,处理一些gcd问题时,质因数分解的考虑方式也值得去尝试。
标签:地方 pre tput mes 产生 顺序 pac inpu int
原文地址:https://www.cnblogs.com/Miracevin/p/9524307.html