【数论】AcWing 1295. X的因子链
https://www.acwing.com/problem/content/1297/
思路:要找符合条件的因子序列,使其长度最长,而且求出最长序列的个数。
显然各序列项之间的的倍数如果是最长了,那一定满足倍数是素数,否则这两个序列之间还可以插入一个新的项。
问题就转换为了,将一个数分解成素数相乘的的形式,求出乘数的个数(算术基本定理),以及有多少种排列方式(多重集的排列)
需要用到素数筛,并记录一个数的最小质因子。
剩下就很简单了。
但是这道题目的一个坑点在于求答案时会爆int,即使答案是一个很小的数,但由于是阶乘的结果作为中间过程,所以中间状态有可能会很大。答案要用long long 存储。
(自己的代码,这份代码最小质因子是现求的)
#include<cstdio> #include<algorithm> #include<cstring> using namespace std; const int N = (2 << 20) + 10; int primes[N],pl; bool st[N]; int fac[N],ex[N],cnt; void get_prime(int n) { for(int i = 2;i <= n;i++) { if(!st[i]) { primes[pl ++ ] = i; } for(int j = 0;primes[j] * i <= n;j ++ ) { int t = primes[j] * i; st[t] = true; if(i % primes[j] == 0) break; } } } int main() { get_prime(N); //for(int i = 0;i < 100;i ++) printf("%d\n",primes[i]); int x; while(scanf("%d", &x) != -1) { cnt = 0; for(int i = 0;x > 1;i ++ ) { if(x % primes[i] == 0) { int f = primes[i]; fac[cnt] = f; ex[cnt] = 0; do{ ex[cnt] ++ ; x /= f; //printf("%d: %d\t",fac[cnt],ex[cnt]); }while(x % f == 0); cnt ++ ; } //printf("%d: %d\t",fac[i],ex[i]); //x /= primes[i]; } //printf("\n"); long long int ans1 = 0, ans2; for(int i = 0;i < cnt;i++) { ans1 += ex[i]; } ans2 = 1; for(int i = ans1;i > 1;i -- ) ans2 *= i; for(int i = 0;i < cnt;i++)//这个循环会爆int,切记 for(int j = ex[i];j > 1; j --) ans2 /= j; printf("%d %d\n",ans1, ans2); } return 0; }

浙公网安备 33010602011771号