CF1174E Ehab and the Expected GCD Problem(动规+数论+分解)

做法

先来填第一个数,为了保证\(f(p)\)最大,第一个数分解一下为\(\prod\limits_{p_i}p_i^{k_i}\)使得\(\sum\limits_{k_i}\)最大

显然第一个数为\(2^x3^y\)\(y≤1\),否则可以把\(3^2\)换成\(2^3\),故第一个数最多有两种选择

定义函数\(Cout(x,y)=\frac{n}{2^x3^y}\)为n以内含因子\(2^x3^y\)的个数

\(f_{i,x,y}\)为填到第\(i\)个数后\(gcd_{j=1}^i a_i=2^x3^y\)的方案数,显然最后的答案为\(f_{n,0,0}\)

code

#include<bits/stdc++.h>
using namespace std;
typedef int LL;
const LL maxn=1e6+9,mod=1e9+7;
LL n;
LL f[maxn][21][2];
inline LL Pow(LL base,LL b){
	LL ret(1);
	while(b){
		if(b&1) ret=ret*base; base=base*base; b>>=1;
	}return ret;
}
inline LL Cout(LL x,LL y){
    LL val(1<<x);
    val*=(y?3:1);
    return n/val;
}
int main(){
    scanf("%d",&n);
    LL p(0);
    while((1<<p)<=n) ++p;
    f[1][--p][0]=1;
    if((1<<p-1)*3<=n) f[1][p-1][1]=1;
    for(LL i=1;i<n;++i)
        for(LL j=0;j<=p;++j){
            for(LL k=0;k<=1;++k){
                f[i+1][j][k]=(f[i+1][j][k]+1ll*f[i][j][k]*(Cout(j,k)-i))%mod;
                if(j) f[i+1][j-1][k]=(f[i+1][j-1][k]+1ll*f[i][j][k]*(Cout(j-1,k)-Cout(j,k)))%mod;
                if(k) f[i+1][j][k-1]=(f[i+1][j][k-1]+1ll*f[i][j][k]*(Cout(j,k-1)-Cout(j,k)))%mod;
            }
        }
    printf("%d",f[n][0][0]);
    return 0;
}
posted @ 2019-06-04 14:52  y2823774827y  阅读(259)  评论(0编辑  收藏  举报