• CSP 模拟19


    A:建设城市(city)

    答案就是至少有0个不满足条件的方案数
    减去至少1个的
    加上至少2个的
    以此类推
    就可以直接做了
    考虑0个的怎么求
    m个队 分成n组 方案数就是C(m-1,n-1);
    不会的建议找数学老师谢罪

    有i个不满足条件的方案数可以用挡板法
    假定此时有i个不满足条件
    那就挑出ik个 令其固定 不参与剩下的分配
    然后在其他的分配好之后 将这i
    k个给到i个城市
    那么这个城市一定不满足
    所以有i个不满足条件的方案数就求出来了





    B:军训队列

    同一个身高的人是等效的
    所以去重之后直接dp就可以了
    dp[i][j] 表示前i个人 分成j组 最小的答案
    (n^2*k)转移就可以了





    C:山屋惊魂

    大模拟





    D:彩球问题

    发现并不关心具体是哪个球
    如果当前的球状态是 1 3 2 3
    而它和1 2 3 3 是等价的
    故我们只关心cnt为1 cnt为2 cnt为3的球有多少个
    因此就可以记搜了
    dp[i][j][k][l] 表示 当前有1个的球有多少种 有2个的球有多少种 有3个的球有多少种 上次放的是哪种球
    然后就可以简单转移了

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn = 14;
    const int mod = 1e8;
    
    struct ll {
    	long long x[5];
    	ll(){memset(x,0,sizeof(x));}
    	friend void operator += (ll &A,ll B) {
    		for(int i = 0;i < 5;++i) A.x[i] += B.x[i];
    		for(int i = 0;i < 5;++i) A.x[i+1] += A.x[i] / mod,A.x[i] %= mod;
    	}
    	friend ll operator * (ll A,int B) {
    		for(int i = 0;i < 5;++i) A.x[i] *= B;
    		for(int i = 0;i < 5;++i) A.x[i+1] += A.x[i] / mod,A.x[i] %= mod;
    		return A;
    	}
    	friend bool operator != (ll &A,int B) { 
    		return A.x[0] != B;
    	}
    	void print(int i = 4){
    		for(;~i;--i) if(x[i]) {printf("%lld",x[i]);break;}
    		for(--i;~i;--i) printf("%08lld",x[i]);
    	}
    };
    
    ll dp[maxn][maxn][maxn][5];
    int a[maxn];
    int cnt[maxn];
    
    ll dfs(int cnt1,int cnt2,int cnt3,int pre){
    	if(dp[cnt1][cnt2][cnt3][pre] != 0) return dp[cnt1][cnt2][cnt3][pre];
    	if(!cnt1 && !cnt2 && !cnt3) {
    		dp[cnt1][cnt2][cnt3][pre].x[0] = 1LL;
    		return dp[cnt1][cnt2][cnt3][pre];
    	}
    	ll ans;
    	if(cnt1) ans += (dfs(cnt1-1,cnt2,cnt3,0) * (cnt1-(pre==1)));
    	if(cnt2) ans += dfs(cnt1+1,cnt2-1,cnt3,1) * (cnt2-(pre==2));
    	if(cnt3) ans += dfs(cnt1,cnt2+1,cnt3-1,2) * (cnt3-(pre==3));
    	return dp[cnt1][cnt2][cnt3][pre] = ans;
    }
    
    int main(){
    	freopen("color.in","r",stdin);
    	freopen("color.out","w",stdout);
    	int n;scanf("%d",&n);
    	for(int i = 1;i <= n;++i) scanf("%d",&a[i]),cnt[a[i]]++;
    	dfs(cnt[1],cnt[2],cnt[3],0).print();
    	return 0;
    }
    
    
    如初见 与初见
  • 相关阅读:
    视频直播架构
    day1 python 入门
    python 多用户登录
    mysql innobackup 备份脚本
    ADT离线安装
    真机调试adb:wait for device 解决方案
    php中的魔术方法
    整理资料
    PostgreSQL表空间_数据库_模式_表_用户角色之间的关系[转]
    PHP获取文件夹的大小
  • 原文地址:https://www.cnblogs.com/HISKrrr/p/13849210.html
Copyright © 2020-2023  润新知