zoukankan      html  css  js  c++  java
  • Avito Cool Challenge 2018:C. Colorful Bricks

    C. Colorful Bricks

    题目链接:https://codeforces.com/contest/1081/problem/C

    题意:

    有n个横向方块,一共有m种颜色,然后有k个方块的颜色与其左边的颜色不同(第一个除外),问一共有多少染色方案。

    题解:

    我们首先来考虑一下dp。

    设dp(i,j)为当前第i个方块,一共有j个方块与它前面的方块不同的方案个数。

    那么转移方程为dp(i,j)=dp(i-1,j-1)*(m-1)+dp(i-1,j)。

    代码如下:

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int MOD = 998244353,N = 2005;
    ll n,m,k;
    ll dp[N][N];
    int main(){
        cin>>n>>m>>k;
        dp[1][0]=m;
        for(int i=2;i<=n;i++){
            for(int j=0;j<i;j++){
                dp[i][j]=dp[i-1][j];
                if(j!=0) dp[i][j]=(dp[i][j]+dp[i-1][j-1]*(m-1))%MOD;
            }
        }
        cout<<dp[n][k];
        return 0;
    }
    View Code

    还有一种数学的计数方法。

    我们假设已经选定了k种颜色,除开第一个,那么我们就可以直接把2-n的位置进行缩点,缩成有前一个的颜色不等于后一个颜色的点(因为有一些点的颜色是和之前的点颜色相等的,这种对答案没有贡献,取决于之前的那个颜色)。

    然后第一个位置有m种情况,之后的每个位置都有m-1种情况。

    所以最后答案为C(n-1,k)*m*(m-1)^k。

    代码如下:

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int MOD = 998244353 ,N = 2005;
    ll n,m,k;
    ll C[N][N];
    ll qp(ll a,ll b){
        ll ans = 1;
        while(b){
            if(b&1) ans=(a*ans)%MOD;
            a=(a*a)%MOD;
            b>>=1;
        }
        return ans ;
    }
    int main(){
        cin>>n>>m>>k;
        C[0][0]=C[1][1]=1;
        for(int i=1;i<=n;i++) C[i][0]=1;
        for(int i=2;i<=n;i++)
            for(int j=1;j<=i;j++)
                C[i][j]=(C[i-1][j-1]+C[i-1][j])%MOD;
        ll ans = (C[n-1][k]*m)%MOD;
    
        cout<<ans*qp(m-1,k)%MOD<<endl;
        return 0;
    }
    View Code
  • 相关阅读:
    面向对象的设计模式2
    数据结构
    算法题目1
    5.7(1) 反射
    hashMap原理(java8)
    6.1 接口
    18.1 线程
    13.2 具体的集合
    scrapy(2)——scrapy爬取新浪微博(单机版)
    5.1 类、超类和子类
  • 原文地址:https://www.cnblogs.com/heyuhhh/p/10135005.html
Copyright © 2011-2022 走看看