ccf 201312-04 有趣的數(組合數學)

問題描述
  咱們把一個數稱爲有趣的,當且僅當:
  1. 它的數字只包含0, 1, 2, 3,且這四個數字都出現過至少一次。
  2. 全部的0都出如今全部的1以前,而全部的2都出如今全部的3以前。
  3. 最高位數字不爲0。
  所以,符合咱們定義的最小的有趣的數是2013。除此之外,4位的有趣的數還有兩個:2031和2301。
  請計算剛好有n位的有趣的數的個數。因爲答案可能很是大,只須要輸出答案除以1000000007的餘數。
輸入格式
  輸入只有一行,包括剛好一個正整數n (4 ≤ n ≤ 1000)。
輸出格式
  輸出只有一行,包括剛好n 位的整數中有趣的數的個數除以1000000007的餘數。
樣例輸入
4
樣例輸出
3
題目分析 :答案給的是動態規劃  但我以爲用組合數學也是很簡單 便於理解的  (之前寫的,再看竟然看不懂了,睡覺的時候又忽然想到了,太笨了。qwq
 1 #include<cstdio>
 2 #include<iostream>
 3 #include<algorithm>
 4 using namespace std;  5 typedef long long LL;  6 const LL p=1e9+7;  7 int n;  8 LL qpow(LL a,LL x) {// 功能 快速冪 a^x 求逆元
 9     LL ans=1; 10     while (x) { 11         if (x&1) { 12            ans=ans*a%p; 13  } 14         a=a*a%p; 15         x=x>>1; 16  } 17     return ans; 18 } 19 LL f(int a,int b) {// 排列組合 C (a,b)=a!/((a-b)!*b!)
20     if (b>a-b) b=a-b; 21     if (b==0) return 1; 22     LL x=a-b+1; 23     LL y=1; 24     LL t1=1,t2=1; 25     for (int i=1;i<=b;i++) { 26         t1=t1*(x++)%p; 27         t2=t2*(y++)%p; 28  } 29     LL ans=t1*qpow(t2,p-2)%p; 30     return ans; 31 } 32 int main () 33 { 34     while (~scanf ("%d",&n) ) { 35         LL sum=0; 36         for (int i=2;i<=n-2;i++) 37         // 首先第一位必定是2 ,按照組合數學原則 ,先放特殊元素,先放01 每次選擇i個位置C(n-1,i)放0和1 38         // 由於0和1都必須出現 而且0在1的前面 因此i個位置有i-1種可能(最小1個0,最多i-1個0,而且0和1的位置固定) 39         // 而後在剩餘的(n-1-i)位置放2和3 由於第一位是2 (因此n-1-i個位置最少一個3,最多n-1-i個3)
40             sum=( (f(n-1,i)*(i-1)%p)*(n-1-i)%p+sum )%p; 41         printf("%lld\n",sum); 42  } 43     return 0; 44 }
相關文章
相關標籤/搜索