2015-06-26 21:43:37

传送门

总结:这场做出了两题,都是数学类的,速度还可,回到黄咯~

反思:第一题没看到数据范围,用了比较麻烦的逆元预处理。第二题纠结题意过久。第三题思维不够强,没想到....

 

A题:组合数

  题意:有 k 种颜色的球,颜色号分别为1~k,每种球 ci 个(1 <= k,c <= 1000),让排成一排,使得第 i 种颜色的最后一个球必须在第 i-1 种颜色的最后一个球的后面,问有多少种这样的排列。

  思路:从末尾往前面的考虑,最后一个位置必定放第 k 种颜色的球,那么该种颜色剩下的 ck-1 个球就随便放了,有 C(n-1,ck-1)种,这样剩下 n - ck 个位置,再考虑第 k-1 种颜色的球,以此类推即可。就是:C(n-1,ck-1) * C(n-ck-1,c(k-1) - 1) * ....

#include <cstdio>
#include <ctime>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <vector>
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;

#define getmid(l,r) ((l) + ((r) - (l)) / 2)
#define MP(a,b) make_pair(a,b)
#define PB(a) push_back(a)

typedef long long ll;
typedef pair<int,int> pii;
const double eps = 1e-8;
const int INF = (1 << 30) - 1;
const ll mod = 1000000007LL;
const int MAXN = 1000000;

int k,c[1010],sum;
ll fac[MAXN + 10],afac[MAXN + 10];

ll Q_pow(ll x,ll y){
    x %= mod;
    ll res = 1;
    while(y){
        if(y & 1) res = res * x % mod;
        x = x * x % mod;
        y >>= 1;
    }
    return res;
}

void Pre(){
    fac[0] = afac[0] = 1;
    for(int i = 1; i <= MAXN; ++i) fac[i] = fac[i - 1] * (ll)i % mod;
    afac[MAXN] = Q_pow(fac[MAXN],mod - 2);
    for(int i = MAXN; i >= 1; --i) afac[i - 1] = afac[i] * i % mod;
}

ll C(int n,int m){
    if(m > n) return 0;
    return fac[n] * afac[n - m] % mod * afac[m] % mod;
}

int main(){
    Pre();
    sum = 0;
    scanf("%d",&k);
    for(int i = 1; i <= k; ++i){
        scanf("%d",&c[i]);
        sum += c[i];
    }
    ll ans = 1;
    for(int i = k; i >= 1; --i){
        ans = ans * C(sum - 1,c[i] - 1) % mod;
        sum -= c[i];
    }
    printf("%I64d\n",ans % mod);
    return 0;
}
View Code

相关文章:

  • 2022-12-23
  • 2022-12-23
  • 2022-01-28
  • 2021-06-12
  • 2022-02-12
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
猜你喜欢
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
相关资源
相似解决方案