zoukankan      html  css  js  c++  java
  • Flipping Game(DP+组合数)

    题目链接:https://cn.vjudge.net/problem/ZOJ-4114

    题目大意:给你n个开关,一共是kk轮,一轮可以关m个灯(这m个灯必须都不同),问你有多少种方法能从初始状态到达最终状态。

    具体思路:dp[i][j] 表示到第i轮的时候,当前正确的为j的这种情况有多少个。

    i : 1->kk 

    j : 0->m

    k:0->n

    dp[ i ][ k - j + m - j ] += dp[ i - 1 ][ k ] * C(k,j) * C( n - k , m - j).

    第i轮,合法的从k正确的里面选出j个合法的变成非合法的,然后从剩余的n-k个中选择m-j个非法的变成合法的。

    AC代码:

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 # define ll long long
     4 # define inf 0x3f3f3f3f
     5 const int maxn = 2e5+100;
     6 const int N = 100+10;
     7 const ll mod = 998244353;
     8 char str1[maxn],str2[maxn];
     9 ll dp[N][N];
    10 ll fac[N],inv[N];
    11 ll  qsm(ll t1,ll t2)
    12 {
    13     ll ans=1ll;
    14     while(t2)
    15     {
    16         if(t2&1)
    17             ans=ans*t1%mod;
    18         t1=t1*t1%mod;
    19         t2>>=1;
    20     }
    21     return ans;
    22 }
    23 
    24 void init()
    25 {
    26     fac[1]=fac[0]=1ll;
    27     for(ll i=2; i<N; i++)
    28     {
    29         fac[i]=(fac[i-1]*i)%mod;
    30     }
    31     inv[N-1]=qsm(fac[N-1],mod-2ll);
    32     for(ll i=N-2; i>=0; i--)
    33     {
    34         inv[i]=(inv[i+1]*(i+1ll))%mod;
    35     }
    36 }
    37 ll C(ll n,ll r)
    38 {
    39     if(r==0||n==r)
    40         return 1ll;
    41     return  (fac[n]*inv[r]%mod*inv[n-r]%mod)%mod;
    42 }
    43 int main()
    44 {
    45     init();
    46     int T;
    47     scanf("%d",&T);
    48     while(T--)
    49     {
    50         memset(dp,0,sizeof(dp));
    51         int n,kk,m;
    52         scanf("%d %d %d",&n,&kk,&m);
    53         scanf("%s",str1);
    54         scanf("%s",str2);
    55         int len1=strlen(str1);
    56         int len2=strlen(str2);
    57         int num=0;
    58         for(int i=0; i<len1; i++)
    59         {
    60             if(str1[i]==str2[i])
    61                 num++;
    62         }
    63         dp[0][num]=1ll;
    64         for(ll i=1; i<=kk; i++)
    65         {
    66             for(ll j=0; j<=m; j++)
    67             {
    68                 for(ll k=0; k<=n; k++)
    69                 {
    70                     if(k-j>=0&&(n-k)>=(m-j))
    71                     {
    72                         dp[i][k-j+m-j]=(dp[i][k-j+m-j]+dp[i-1][k]%mod*C(k,j)%mod*C(n-k,m-j))%mod;
    73                         dp[i][k-j+m-j]%=mod;
    74                     }
    75                 }
    76             }
    77         }
    78         printf("%lld
    ",dp[kk][n]);
    79     }
    80     return 0;
    81 }
  • 相关阅读:
    VS2012的恢复默认窗口的基本常用设置
    在 CentOS 6.4 上安装 CloudStack 4.2
    centos7上安装mysql
    myeclipse安装aptana插件
    访问WEB-INF下的JSP (转载)
    通过字节流复制大文件内容到指定的文件
    java 通过bufferedReader和bufferedWriter 拷贝文件
    Date类获取日期的方法失效的解决办法
    java中string 类型的对象间比较的学习笔记
    ubuntu下搭建nfs服务器
  • 原文地址:https://www.cnblogs.com/letlifestop/p/10857818.html
Copyright © 2011-2022 走看看