最大公约数 [动态规划]
最优情况中, 每次变化都是 质因数分解中的一个质因子次数减少 , 所以 为 中 质因数分解质数次幂的和 的 最大值 加上 .
首先 分解质因数后一定是 的形式, 其中
假设存在 , 使得 分解质因数后为 , 则 可以替换为 ,答案不会更差, 因此 .
接下来计算 的 的个数, 考虑 从左往右 填数, 前面的数字一定是 的形式,
设 表示 填了前 个数字, 前 个数字的 为 的方案数,
初值
转移 时使得 或 至多其中一个减一,
-
不变:
-
减 :
-
减 :
最后答案即为 .
#include<bits/stdc++.h>
#define reg register
const int mod = 1e9 + 7;
const int maxn = 1e6 + 5;
int N;
int F[maxn][22][2];
int Ksm(int a, int b){ int s=1; while(b){ if(b&1)s=1ll*s*a%mod; a=1ll*a*a%mod;b>>=1; } return s; }
int main(){
scanf("%d", &N); int t = log2(N);
F[1][t][0] = 1; if(Ksm(2, t-1)*3 <= N) F[1][t-1][1] = 1;
for(reg int i = 2; i <= N; i ++)
for(reg int x = 0; x <= t; x ++)
for(reg int y = 0; y <= 1; y ++){
int &cur = F[i][x][y], t1 = Ksm(2,x)*Ksm(3,y), t2 = Ksm(2,x+1)*Ksm(3,y), t3 = Ksm(2,x)*Ksm(3,y+1);
if(N/t1 > i-1) cur = (cur + 1ll*F[i-1][x][y]*(N/t1-i+1)%mod) % mod;
if(x != t) cur = (cur + 1ll*F[i-1][x+1][y]*(N/t1 - N/t2)%mod) % mod;
if(y != 1) cur = (cur + 1ll*F[i-1][x][y+1]*(N/t1 - N/t3)%mod) % mod;
}
printf("%d\n", F[N][0][0]);
return 0;
}