zoukankan      html  css  js  c++  java
  • 题解 LOJ3284 「USACO 2020 US Open Platinum」Exercise

    对于一个排列,它的操作次数是它所有循环圈长度的(operatorname{lcm})

    因为答案是求乘积。我们可以分别计算每个质数的贡献。

    对于一个质数(p),它对答案的贡献是每个排列中,所有循环圈长度(分解质因数后)(p)的次数的最大值之和。即:

    [ans=prod_{p}p^{sum_{ ext{一个排列}}max_{ ext{一个循环圈}i}{len_i ext{里}p ext{的次数}}} ]

    考虑求指数部分,对(m-1)取模。即:

    [sum_{ ext{一个排列}}max_{ ext{一个循环圈}i}{len_i ext{里}p ext{的次数}} ]

    考虑min-max容斥。则上式可以转化为:

    [sum_{ ext{一个排列}}sum_{ ext{循环圈的一个子集}s}(-1)^{|s|+1}min_{iin s}{len_i ext{里}p ext{的次数}} ]

    最小值,可以转化为枚举一个值(x),若所有数都(geq x),则对最小值(+1)。于是上式可以写成:

    [sum_{ ext{一个排列}}sum_{ ext{循环圈的一个子集}s}(-1)^{|s|+1}sum_{x=1}^{n}prod_{iin s}[len_i ext{里}p ext{的次数}geq x] ]

    我们枚举质数(p),再枚举(x)。问题转化为,求所有排列的,所有循环圈的子集中,有多少个子集使得子集内所有循环圈的大小都是(p^x)的倍数。每个子集要带上容斥系数((-1)^{|s|+1})

    考虑DP。设子集内所有循环圈大小之和是(icdot p^x)的方案数为(dp[i])。转移时,类似于带标号无向连通图计数的方法,我们钦定一个点为一号点。枚举一号点所在的循环圈的大小为(jcdot p^x)。则可以这么转移:

    [dp[i]=sum_{j=1}^{i}(-1)cdot dp[i-j]cdot {icdot p^x-1choose jcdot p^x-1}(jcdot p^x-1)! ]

    DP部分的时间复杂度是(O(frac{n^2}{p^{2x}}))的。在外层枚举(p)(x)后,总复杂度是(n^2sum_{p}sum_{x}frac{1}{p^{2x}}leq n^2sum_{i=1}^{n}frac{1}{i^2}leqfrac{n^2pi^2}{6}),也就是(O(n^2))

    参考代码:

    在LOJ查看

    //LOJ3284
    #include <bits/stdc++.h>
    using namespace std;
    
    #define pb push_back
    #define mk make_pair
    #define lob lower_bound
    #define upb upper_bound
    #define fi first
    #define se second
    #define SZ(x) ((int)(x).size())
    
    typedef unsigned int uint;
    typedef long long ll;
    typedef unsigned long long ull;
    typedef pair<int,int> pii;
    
    /*  ------  by:duyi  ------  */ // myt天下第一
    const int MAXN=7500;
    int n,m,fac[MAXN+5],comb[MAXN+5][MAXN+5],p[MAXN+5],cnt_p,flag[MAXN+5];
    bool v[MAXN+5];
    int pow_mod(int x,int i,int MOD){
    	int y=1;
    	while(i){
    		if(i&1)y=(ll)y*x%MOD;
    		x=(ll)x*x%MOD;
    		i>>=1;
    	}
    	return y;
    }
    int calc(int s,int MOD){
    	static int dp[MAXN+5];
    	int lim=n/s;
    	dp[0]=MOD-1;
    	for(int i=1;i<=lim;++i){
    		dp[i]=0;
    		for(int j=1;j<=i;++j)if(dp[i-j]){//钦定一个一号点,一号点所在的环长为j*s
    			dp[i]=(dp[i]-(ll)dp[i-j]*comb[i*s-1][j*s-1]%MOD*fac[j*s-1]%MOD+MOD)%MOD;
    		}
    	}
    	int res=0;
    	for(int i=1;i<=lim;++i)res=(res+(ll)dp[i]*comb[n][i*s]%MOD*fac[n-i*s]%MOD)%MOD;
    	return res;
    }
    int main() {
    	cin>>n>>m;
    	fac[0]=1;
    	for(int i=1;i<=n;++i)fac[i]=(ll)fac[i-1]*i%(m-1);//阶乘
    	comb[0][0]=1;
    	for(int i=1;i<=n;++i){
    		comb[i][0]=1;
    		for(int j=1;j<=i;++j){
    			int& x=comb[i][j];
    			x=comb[i-1][j]+comb[i-1][j-1];
    			x=(x<(m-1)?x:x-(m-1));
    		}
    	}//组合数
    	for(int i=2;i<=n;++i){
    		if(!v[i])p[++cnt_p]=i;
    		for(int j=1;j<=cnt_p&&p[j]*i<=n;++j){
    			v[i*p[j]]=1;
    			if(i%p[j]==0)break;
    		}
    	}//质数
    	for(int i=1;i<=cnt_p;++i){
    		for(int j=p[i];j<=n;j*=p[i]){
    			flag[j]=p[i];
    		}
    	}//质数的幂
    	
    	int ans=1;
    	for(int i=1;i<=n;++i)if(flag[i]){
    		ans=(ll)ans*pow_mod(flag[i],calc(i,m-1),m)%m;
    	}
    	cout<<ans<<endl;
    	return 0;
    }
    
  • 相关阅读:
    SrsDataConnector The SQL Server Reporting Services account is a local user and is not supported.
    Marketing with Microsoft Dynamics CRM IDEA CONFERENCE
    Discuz!X 系列 HTTP_X_FORWARDED_FOR 绕过限制进行密码爆破
    PHPCMS v9.5.6 通杀getshell(前台)
    PHPCMS v9.5.8-设计缺陷可重置前台任意用户密码
    PHPCMS v9.6.0 任意用户密码重置
    PHPCMS V9 任意文件下载(Windows)
    Joomla!3.7.0 Core SQL注入漏洞动态调试草稿
    利用FOFA搜索WatchGuard防火墙
    如何删除Windows休眠文件(hiberfil.sys)
  • 原文地址:https://www.cnblogs.com/dysyn1314/p/12745877.html
Copyright © 2011-2022 走看看