zoukankan      html  css  js  c++  java
  • CH5E26 扑克牌

    题意

    描述

    一副不含王的扑克牌由52张牌组成,由红桃、黑桃、梅花、方块4组牌组成,每组13张不同的面值。现在给定52
    张牌中的若干张,请计算将它们排成一列,相邻的牌面值不同的方案数。
    牌的表示方法为XY,其中X为面值,为2、3、4、5、6、7、8、9、T、J、Q、K、A中的一个。Y为花色,为S、
    H、D、C中的一个。如2S、2H、TD等。

    输入格式

    第一行为一个整数T,为数据组数。
    之后每组数据占一行。这一行首先包含一个整数N,表示给定的牌的张数,接下来N个由空格分隔的字符串,每个字符串长度为2,表示一张牌。每组数据中的扑克牌各不相同。

    输出格式

    对于每组数据输出一行,形如"Case #X: Y"。X为数据组数,从1开始。Y为可能的方案数,由于答案可能很大,
    请输出模2^64之后的值。

    样例输入

    5
    1 TC
    2 TC TS
    5 2C AD AC JC JH
    4 AC KC QC JC
    6 AC AD AS JC JD KD

    样例输出

    Case #1: 1
    Case #2: 0
    Case #3: 48
    Case #4: 24
    Case #5: 120

    数据范围与约定

    • 1 ≤ T ≤ 20000,1 ≤ N ≤ 52
            </article>
    

    分析

    由于相同种类的牌的牌数只有1-4,而方案数容斥跟牌数相关,所以考虑以牌数建立状态。设(F[a][b][c][d]),表示1张的有a种,2张的有b种,3张的有c种,4张的有d种。

    考虑如何容斥。首先如果放的是1张牌的,就只有a种方案。当牌数大于1时,用一个决策后的状态计算,要减去它转移到的不合法的状态。

    代码

    #include<bits/stdc++.h>
    #define rg register
    #define il inline
    #define co const
    template<class T>il T read(){
        rg T data=0,w=1;rg char ch=getchar();
        while(!isdigit(ch)) {if(ch=='-') w=-1;ch=getchar();}
        while(isdigit(ch)) data=data*10+ch-'0',ch=getchar();
        return data*w;
    }
    template<class T>il T read(rg T&x) {return x=read<T>();}
    typedef unsigned long long ull;
    co int N=20;
    int n,num[N],c[N];
    ull f[N][N][N][N];
    char s[N];
    ull dp(int a,int b,int c,int d){
    	if(f[a][b][c][d]!=-1LLU) return f[a][b][c][d];
    	ull ans=0;
    	if(a>0) ans+=(ull)a*dp(a-1,b,c,d);
    	if(b>0) ans+=(ull)b*2*(dp(a+1,b-1,c,d)-dp(a,b-1,c,d));
    	if(c>0) ans+=(ull)c*3*(dp(a,b+1,c-1,d)-2*(dp(a+1,b,c-1,d)-dp(a,b,c-1,d)));
    	if(d>0) ans+=(ull)d*4*(dp(a,b,c+1,d-1)-3*(dp(a,b+1,c,d-1)-2*(dp(a+1,b,c,d-1)-dp(a,b,c,d-1))));
    	return f[a][b][c][d]=ans;
    }
    int work(char c){
    	switch (c){
    		case 'T': return 10;
    		case 'J': return 11;
    		case 'Q': return 12;
    		case 'K': return 13;
    		case 'A': return 1;
    		default: return c-'0';
    	}
    }
    void Poker(int t){
    	read(n);
    	memset(num,0,sizeof num);
    	memset(c,0,sizeof c);
    	for(int i=1;i<=n;++i)
    		scanf("%s",s+1),++num[work(s[1])];
    	for(int i=1;i<=13;++i) ++c[num[i]];
    	printf("Case #%d: %llu
    ",t,dp(c[1],c[2],c[3],c[4]));
    }
    int main(){
    	memset(f,-1,sizeof f);
    	f[0][0][0][0]=1;
    	for(int T=read<int>(),t=1;t<=T;++t) Poker(t);
    	return 0;
    }
    
  • 相关阅读:
    软件测试描述错误
    软件测试homework2
    第九次
    第七次作业
    第六次作业
    第五次作业
    第四次作业
    第三次
    软件测试Lab2 Selenium及自动化测试
    软件测试(四)主路径覆盖hw3
  • 原文地址:https://www.cnblogs.com/autoint/p/10803388.html
Copyright © 2011-2022 走看看