题意:有三种岛,分别有 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; }