CodeForces 869C The Intriguing Obsession 思维, dp或组合数

CodeForces 869C

题意:有三种岛,分别有 a, b, c 个。可互相连边,限制:对于相同颜色的两个岛,两者不能直接连边,且最短距离要 >= 3 。 问有多少种连边方案。

tags: 想不到啊想不到。。

把三种岛分成三大块来看,只要在每两块之间考虑连边即可。

想到这里就很好做了,组合数或 dp 都可以。

dp :     for(i)  for(j)  dp[i][j] = dp[i-1][j] + dp[i-1][j-1]*j   。

组合数:

#include<bits/stdc++.h>
using namespace std;
#pragma comment(linker, "/STACK:102400000,102400000")
#define rep(i,a,b) for (int i=a; i<=b; ++i)
#define per(i,b,a) for (int i=b; i>=a; --i)
#define mes(a,b)  memset(a,b,sizeof(a))
#define INF 0x3f3f3f3f
#define MP make_pair
#define PB push_back
#define fi  first
#define se  second
typedef long long ll;
const int N = 200005, mod = 998244353;

ll fac[N], inv[N];
ll fpow(ll a, ll b) {ll ans=1; for(;b;a=a*a%mod,b>>=1)if(b&1)ans=ans*a%mod; return ans;}
ll Inv(ll x) { return fpow(x, mod-2); }
ll C(ll a, ll b)
{
    if(b==0 || a==b) return 1;
    return fac[a]*inv[b]%mod*inv[a-b]%mod;
}
ll A(ll a, ll b)
{
    if(a-b==0) return fac[a];
    return fac[a]*inv[a-b]%mod;
}
void Init(int _n)
{
    fac[0]=1;
    rep(i,1,_n)
        fac[i]=fac[i-1]*i%mod, inv[i]=Inv(fac[i])%mod;
}

ll  get(ll n, ll m)
{
    ll  ans = 0;
    for(ll i=0; i<=min(n, m); ++i)
        ( ans +=  C(n,i)*C(m,i)%mod*A(i,i)%mod ) %= mod;
    return ans;
}

ll  n, a, b, c;
int main()
{
    Init(N-1);
    scanf("%lld%lld%lld", &a, &b, &c);
    ll  ans = 1;
    ( ans *= get(a, b) ) %= mod;
    ( ans *= get(a, c) ) %= mod;
    ( ans *= get(b, c) ) %= mod;
    printf("%lld
", (ans+mod)%mod);

    return 0;
}
原文地址:https://www.cnblogs.com/sbfhy/p/7668761.html