zoukankan      html  css  js  c++  java
  • Luogu P4996 咕咕咕

    题目传送门

    题目名字真是十分契合Luogu的性质啊

    IG NB


    (3^n)的子集枚举不会……看了题解后只会正解

    对于每个状态,其实对我们有用的只有这个状态中有多少个(1),而(1)的位置我们并不关心,因为具有相同个数个(1)的状态,它们出现的次数一定是相同的。

    所以我们考虑用dp[i]表示有(i)(1)的方案数,因为我们可以一步一步的填(1),所以dp[i]=dp[i]+dp[i-j]*c[i][j],其中c[i][j]表示(C^j_i),即(dp[i]=sumlimits_{j=1}^{i} dp[i-j] cdot C^j_i)
    有了上面的式子,我们预处理组合数和(dp[i])就好了

    一定要多取模,不然会炸。 十年OI一场空,忘掉取模见祖宗

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define mod 998244353
    #define LL long long
    using namespace std;
    LL c[30][30];
    LL dp[30];
    void init(){
    	c[0][0]=1;
    	for(int i=1;i<=20;i++) c[i][0]=1;
    	for(int i=1;i<=20;i++)
    	  for(int j=1;j<=i;j++)
    	    c[i][j]=(c[i-1][j]+c[i-1][j-1])%mod;
    	dp[0]=1;
    	for(int i=1;i<=20;i++)
    	  for(int j=1;j<=i;j++)
    		dp[i]=(dp[i]+(dp[i-j]*c[i][j])%mod)%mod;
    }
    int read(){
    	char c=getchar();
    	while(c<'0'||c>'9') c=getchar();
    	return c-48;
    }
    LL cnt,ans;
    int main(){
    	init();
    	int n,m; cin>>n>>m;
    	for(int i=1;i<=m;i++){
    		cnt=0;
    		for(int j=1;j<=n;j++)
    		  if(read()) cnt++;
    		LL k; cin>>k;
    		ans=(ans+(((k*dp[cnt])%mod)*dp[n-cnt])%mod)%mod;
    	}
    	cout<<ans;
    	return 0;
    }
    
  • 相关阅读:
    资源链接
    python pip下载速度慢的解决方法
    淘宝 NPM 镜像
    python学习链接
    Linux升级python3之后yum不能正常使用解决方法一:重新配置yum源
    rand和srand的用法
    static与volatile的用法
    CentOS 7
    C++类(Class)总结
    简单的linux命令
  • 原文地址:https://www.cnblogs.com/morslin/p/11854962.html
Copyright © 2011-2022 走看看