• [CSP-S模拟测试]:建设城市(city)(组合数学+容斥)


    题目传送门(内部题8)


    输入格式

    一行三个整数$n,m,k$。


    输出格式

    一行一个整数表示答案。对$998244353$取模。


    样例

    样例输入

    3 7 3

    样例输出

    6


    数据范围与提示

    对于10%的数据,$1leqslant n,m,kleqslant 10$。
    对于40%的数据,$1leqslant n,m,kleqslant 1,000$。
    对于70%的数据,$1leqslant n,m,kleqslant {10}^5$。
    对于100%的数据,$1leqslant nleqslant {10}^9$,$1leqslant n,kleqslant {10}^7$。


    题解

    $20\%$算法:

    如果$n>m$或$n<m imes k$那么一定没有方案,直接$puts("0");$即可。

    时间复杂度:$Theta(1)$。

    期望的分:$0$分。

    实际的分:$20$分。

    $10\%$算法:

    爆搜,枚举所有情况即可。

    时间复杂度:$Theta(n^k)$。

    期望的分:$10$分。

    实际的分:$10$分。

    $40\%$算法:

    考虑$DP$,设$dp[i][j]$为到第$i$个城市,一共用了$j$个建设队的方案数。

    那么可以列出状态转移方程:$dp[i][j]=sum limits_{k=1}^{min(k,m)}dp[i-1][j-k]$。

    时间复杂度:$Theta(n^3)$。

    期望的分:$40$分。

    实际的分:$40$分。

    $100\%$算法:

    考虑容斥,挡板法。

    这个问题可以转化为,在$m$个物品中插入$n-1$个挡板,挡板不能插在一起,那么方案数就是$C_{m-1}^{n-1}$。

    现在需要减去不合法的方案数,设至少有$i$个城市不合法,那么方案数就是$C_n^i imes C_{m-i imes k-1}^{n-1}$,可以理解为,我先将那$i imes k$个不合法的扔掉,再在$m-i imes k$里面选合法的即可。

    利用容斥统计答案即可。

    时间复杂度:$Theta(m)$。

    期望的分:$100$分。

    实际的分:$100$分。


    代码时刻

    $20\%$算法:

    #include<bits/stdc++.h>
    using namespace std;
    int n,m,k;
    int main()
    {
    	scanf("%d%d%d",&n,&m,&k);
    	if(n>m||n*k<m)puts("0");
    	return 0;
    }
    

    $40\%$算法:

    #include<bits/stdc++.h>
    using namespace std;
    int dp[7000][7000];
    int main()
    {
    	int n,m,k;
    	scanf("%d%d%d",&n,&m,&k);
    	for(int i=1;i<=k;i++)dp[1][i]=1;
    	for(int i=2;i<=n;i++)
    		for(int j=i;j<=m;j++)
    			for(int l=1;l<=min(k,m);l++)
    				dp[i][j]=(dp[i][j]+dp[i-1][j-l])%998244353;
    	cout<<dp[n][m]<<endl;
    	return 0;
    }
    

    $100\%$算法:

    #include<bits/stdc++.h>
    using namespace std;
    long long n,m,k;
    long long jc[100000001],qsm[100000001];
    long long ans;
    long long qpow(long long x,long long y)
    {
    	long long res=1;
    	while(y)
    	{
    		if(y&1)res=res*x%998244353;
    		x=x*x%998244353;
    		y>>=1;
    	}
    	return res;
    }
    void pre_work()
    {
        jc[0]=1;
        for(int i=1;i<=m;i++)
            jc[i]=1LL*jc[i-1]*i%998244353;
        for(int i=0;i<=m;i++)
            qsm[i]=qpow(jc[i],998244351)%998244353;
    }
    long long cm(long long x,long long y)
    {
        return jc[x]*qsm[y]%998244353*qsm[x-y]%998244353;
    }
    long long lucas(long long x,long long y)
    {
        if(!y)return 1;
        return cm(x%998244353,y%998244353)*lucas(x/998244353,y/998244353)%998244353;
    }
    int main()
    {
    	scanf("%lld%lld%lld",&n,&m,&k);
    	if(n>m||n*k<m){puts("0");return 0;}
    	pre_work();
    	long long flag=-1;
    	ans=jc[m-1]*qsm[n-1]%998244353*qsm[m-n]%998244353;
    	for(int i=1;i<=n;i++)
    	{
    		if(m-i*k<n)continue;
    		ans=(ans+flag*lucas(n,i)%998244353*lucas(m-i*k-1,n-1)+998244353)%998244353;
    		flag=-flag;
    	}
    	printf("%lld",(ans+998244353)%998244353);
    	return 0;
    }
    

    rp++

  • 相关阅读:
    [SQL server] IF ELSE 和 CASE WHEN 的用法
    SQL server游标基本结构
    SQLserver查看某个视图的创建语句
    SqlServer和Oracle修改表结构语句
    IE浏览器部分js代码不生效的问题
    SQL server将查询到的多行结果,拼接成字符串(列转行)
    SQL server将某个字符串将按指定字符分解成子字符串(行转列)
    安装weblogic时,运行configure.cmd报错、闪退、无法创建域
    黑苹果相关工具
    黑苹果安装问题集
  • 原文地址:https://www.cnblogs.com/wzc521/p/11329755.html
Copyright © 2020-2023  润新知