1. 程式人生 > >[CodeForces-869C]The Intriguing Obsession

[CodeForces-869C]The Intriguing Obsession

getchar() tdi mod nbsp print gui ret git while

題目大意:
  有三種顏色的點,a個紅色,b個藍色,c個紫色。
  現在你要連邊,保證相同顏色的點之間距離>=3,問有多少種合法的連邊方案。(不一定連通)

思路:
  當加上去的邊不滿足條件時,無非是以下兩種情況:
    1.同色點距離=1,同色邊直接相連。
    2.同色點距離=2,某個點直接連向兩個不同的同色點。
  我們可以將這個問題分為三個部分:
    1.a個紅點和b個藍點之間的連邊方案。
    2.b個藍點和c個紫點之間的連邊方案。
    3.a個紅點和c和紫點之間的連邊方案。
  假設我們要在a個紅色和b個藍色之間連k條邊,則總共有C(a,k)*C(b,k)*(k!)種方案。

  我們最少可以連0條邊,最多可以連min(a,b)條邊,則只考慮紅點和藍點的總方案數為sum{C(a,k)*C(b,k)*(k!)|0<=k<=min(a,b)}。
  對於三種情況都可以這樣算。
  顯然這三種情況是不會相互影響的,因此直接將三個答案乘起來就好了。

 1 #include<cstdio>
 2 #include<cctype>
 3 #include<algorithm>
 4 typedef long long int64;
 5 const int N=5001,mod=998244353;
 6 inline int
getint() { 7 register char ch; 8 while(!isdigit(ch=getchar())); 9 register int x=ch^0; 10 while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^0); 11 return x; 12 } 13 int C[N][N]; 14 int main() { 15 for(register int i=0;i<N;i++) { 16 C[i][0
]=1; 17 for(register int j=1;j<=i;j++) { 18 C[i][j]=(C[i-1][j-1]+C[i-1][j])%mod; 19 } 20 } 21 int a=getint(),b=getint(),c=getint(); 22 int ans1=0,ans2=0,ans3=0; 23 for(register int k=0,fact=1;k<=std::min(a,b);fact=(int64)fact*++k%mod) { 24 ans1=((int64)C[a][k]*C[b][k]%mod*fact%mod+ans1)%mod; 25 } 26 for(register int k=0,fact=1;k<=std::min(b,c);fact=(int64)fact*++k%mod) { 27 ans2=((int64)C[b][k]*C[c][k]%mod*fact%mod+ans2)%mod; 28 } 29 for(register int k=0,fact=1;k<=std::min(a,c);fact=(int64)fact*++k%mod) { 30 ans3=((int64)C[a][k]*C[c][k]%mod*fact%mod+ans3)%mod; 31 } 32 printf("%d\n",int((int64)ans1*ans2%mod*ans3%mod)); 33 return 0; 34 }

[CodeForces-869C]The Intriguing Obsession