Codeforces Round #439 (Div. 2) C. The Intriguing Obsession

C. The Intriguing Obsession

题目链接http://codeforces.com/contest/869/problem/C
解题心得:
    1、由于题目中限制了两个相同颜色的点之间长度至少为3,这样就只能两两不同颜色的点相互组合,再将三种组合情况的可能种数乘起来。
    2、然后就是两个不同颜色的点怎么组合的问题,这就是一个记忆化搜索(DP),假如红色点和黄色点相互组合,这样一个红色点可以对应一个黄色点(dp[x][y] = dp[x-1][y-1]*y),或者对应0个黄色点(dp[x][y]=dp[x-1][y]),然后将三种组合情况乘起来。
   

#include<bits/stdc++.h>
using namespace std;
const int maxn = 5010;
const int mod = 998244353;
typedef long long ll;
ll dp[maxn][maxn];

ll solve(ll x,ll y)
{
    if(dp[x][y] > 0)
        return dp[x][y];
    if(x == 0 || y == 0)
        return dp[x][y] = 1;
    return dp[x][y] = (solve(x-1,y)+y*solve(x-1,y-1)%mod)%mod;//可以选择不连接+选择连接(一个点可以选择和y个点中的一个建立映射关系)
}

int main()
{
    ll a,b,c;
    scanf("%lld%lld%lld",&a,&b,&c);
    ll s[3];
    s[0] = a,s[1] = b,s[2] = c;
    sort(s,s+3);//从点数目小的向点数目大的映射

    ll temp1 = solve(s[0],s[1]);
    ll temp2 = solve(s[1],s[2]);
    ll temp3 = solve(s[0],s[2]);

    ll ans = (((temp1*temp2)%mod)*temp3)%mod;//三中可能性是同时存在的,直接乘起来
    printf("%lld",ans);
    return 0;
}
原文地址:https://www.cnblogs.com/GoldenFingers/p/9107261.html