Codeforces Round #439 C
题意:给出a、b、c 3种岛屿的个数,在岛屿之间连线,要求同种岛屿之间的最小距离大于等于3或者不可达,求方案数
思路:最短路只可能是3或者是不可达,画一下图即可知,任意2个不同的岛屿之间的连线与另一个岛屿无关,比如 a b之间的连线和c无关,a b之间可以在满足条件的情况下随便连,连完之后 b c之间同样可以在满足条件的情况下随便连,不需要考虑a的影响,因为a不会对他们造成影响,并且在2种岛屿之间,每一个岛屿最多连一条线,所以很明显了,只要单独两两考虑最后答案相乘即可
AC代码:
#include "iostream" #include "iomanip" #include "string.h" #include "stack" #include "queue" #include "string" #include "vector" #include "set" #include "map" #include "algorithm" #include "stdio.h" #include "math.h" #pragma comment(linker, "/STACK:102400000,102400000") #define bug(x) cout<<x<<" "<<"UUUUU"<<endl; #define mem(a,x) memset(a,x,sizeof(a)) #define step(x) fixed<< setprecision(x)<< #define mp(x,y) make_pair(x,y) #define pb(x) push_back(x) #define ll long long #define endl ("\n") #define ft first #define sd second #define lrt (rt<<1) #define rrt (rt<<1|1) using namespace std; const ll mod=998244353; const ll INF = 1e18+1LL; const int inf = 1e9+1e8; const double PI=acos(-1.0); const int N=1e5+100; ll exp_mod(ll a, ll b, ll p){ ll res = 1; while(b != 0){ if(b&1) res = (res * a) % p; a = (a*a) % p; b >>= 1; } return res; } ll Comb(ll a, ll b, ll p){ if(a < b) return 0; if(a == b) return 1; if(b > a - b) b = a - b; ll ans = 1, ca = 1, cb = 1; for(ll i = 0; i < b; ++i){ ca = (ca * (a - i))%p; cb = (cb * (b - i))%p; } ans = (ca*exp_mod(cb, p - 2, p)) % p; return ans; } ll Lucas(ll n, ll m, ll p){ ll ans = 1; while(n&&m&&ans){ ans = (ans*Comb(n%p, m%p, p)) % p; n /= p; m /= p; } return ans; } ll A[5005]={1}; int main(){ ios::sync_with_stdio(0),cin.tie(0),cout.tie(0); ll a,b,c, ans,ans1=0,ans2=0,ans3=0; cin>>a>>b>>c; for(int i=1; i<=5000; ++i) A[i]=(A[i-1]*i)%mod; for(int i=0; i<=min(a,b); ++i){ ans1+=(((Lucas(a,i,mod)*Lucas(b,i,mod))%mod)*A[i])%mod; ans1%=mod; } for(int i=0; i<=min(a,c); ++i){ ans2+=(((Lucas(a,i,mod)*Lucas(c,i,mod))%mod)*A[i])%mod; ans2%=mod; } for(int i=0; i<=min(b,c); ++i){ ans3+=(((Lucas(b,i,mod)*Lucas(c,i,mod))%mod)*A[i])%mod; ans3%=mod; } ans=(((ans1*ans2)%mod)*ans3)%mod; cout<<ans<<endl; return 0; }