斗地主(dp求方案数,牛客练习赛93)

Linking


题意:

牛牛有 m m m 种类型的牌,每种牌的分值是 a 1 , a 2 … a m a_1,a_2\dots a_m a1,a2am
初始分值为 0 0 0,每回合打出一张牌,新的分值就为上一回合得分加上这张牌的分值再对 k k k 取模。
问,有多少种出牌方案,使得 n n n 回合后,分值中含有字符 7 7 7 或字符 9 9 9
( 1 ≤ n ≤ 100 , 1 ≤ m , k ≤ 50 , 0 ≤ a m < k ) (1≤n≤100,1\le m,k \le50,0\le a_m < k) (1n1001m,k500am<k)

思路:

取模后再相加 等价于 相加后最后再取模
所以,就先按每取模的算,最后取模再判断是否含有7或9。

求方案数,dp经典问题。
状态表示: f[i,j]:前 i 个回合,所得分值为 j 的出牌方案数。
状态转移
当前状态由上一回合的状态转移过来,但是并不知道当前回合出牌种类,所以还要遍历所有种类 jf[i,j] += f[i-1, t-a[j]]
初始化:0 回合得到分值为 0 的方案数f[0,0] = 1

Code:

const int N = 5010, mod = 1e9+7;
int T, n, m;
int a[N];
int f[N][N];

signed main(){
    
    
	int k;
	cin>>n>>m>>k;
	
	for(int i=1;i<=m;i++) cin>>a[i];
	
	sort(a+1,a+m+1);
	
	f[0][0]=1;
	for(int i=1;i<=n;i++)
	{
    
    
		for(int j=1;j<=m;j++)
		{
    
    
			for(int t=a[j];t<=n*k;t++)
			{
    
    
				f[i][t] += f[i-1][t-a[j]];
				f[i][t] %= mod;
			}
		}
	}
	int ans=0;
	for(int i=1;i<=n*k;i++){
    
    
		if((i%k)%10==7 || (i%k)%10==9) ans = (ans+f[n][i])%mod;
	}
	cout<<ans;
	
	return 0;
}

竟然做出来了,挺兴奋的!

猜你喜欢

转载自blog.csdn.net/Mr_dimple/article/details/121878290
今日推荐