zoukankan      html  css  js  c++  java
  • Sky 要玩棋子

    题目:Sky 在玩一个神奇的游戏,这个游戏有n个互不相同的红色棋子和m 个互不相同黑色棋子,任意一个红色棋子都可以和任何一个黑色棋子抵消。Sky 会从这些棋子中选出若干个棋子,Sky想知道:有多少种选择的方案,可以使得 Sky 选择的棋子两两抵消。

    先输入一个T,表示有T组。然后给定T组n,m。答案对1e9+7(考试的时候写成1e+7怒过样例,因为还有特判保留了20分的尊严)

    (1le n,m,Tle 10^6)

    分析:一般人都能想到排列数吧,直接枚举选择棋子的数量,然后乘法原理。答案显然是

    [sum ^{min(n,m)}_{i=1} C_n^i C_m^i ]

    (n^2)预处理组合数表,每个询问(O(n))计算上式即可。

    但是这样显然不是正解,时空复杂度太大了。

    进一步读题,我们可以发现棋子是可以放在一起拿的,没必要分成两堆挑。

    假设我选出了i枚红棋,则我还要选i颗黑棋,也就是说,还有m-i颗黑棋没被选,那么就是说,选i颗红棋子,再选m-i颗黑棋表示不选。
    这两个是等价的。

    而上述第二种表述,其实就是在全部的棋子选出m颗棋子,i颗红棋,m-i个黑棋。因为不能什么都不选,答案还要减去1。

    答案就是

    [C_{n+m}^m-1 ]

    预处理阶乘,每个询问(O(1))计算即可

    #include<bits/stdc++.h>
    #define rep(i,j,k) for(register int i(j);i<=k;++i)
    #define drp(i,j,k) for(register int i(j);i>=k;--i)
    using namespace std;
    typedef long long lxl;
    template<typename T>
    inline T  max(T &a, T &b) {
    	return a > b ? a : b;
    }
    template<typename T>
    inline T  min(T &a, T &b) {
    	return a < b ? a : b;
    }
    inline char gt() {
    	static char buf[1 << 21], *p1 = buf, *p2 = buf;
    	return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++;
    }
    
    template <typename T>
    inline void  read(T &x) {
    	register char ch = gt();
    	x = 0;
    	int w(0);
    	while(!(ch >= '0' && ch <= '9'))w |= ch == '-', ch = gt();
    	while(ch >= '0' && ch <= '9')x = x * 10 + (ch & 15), ch = gt();
    	w ? x = ~(x - 1) : x;
    }
    template <typename T>
    inline void out(T x) {
    	if(x < 0) x = -x, putchar('-');
    	char ch[20];
    	int num(0);
    	while(x || !num) ch[++num] = x % 10 + '0', x /= 10;
    	while(num) putchar(ch[num--]);
    	putchar('
    ');
    }
    const int mod = 1e9 + 7;
    const int MX=2e6+79;
    int n, m, k, tot;
    lxl ans;
    lxl fac[MX+111],inv_fac[MX+111];
    
    inline lxl Quick_Pow(lxl a, lxl b,lxl mod) {
    	lxl res(1 % mod);
    	for(; b; b >>= 1) {
    		if(b & 1)
    			res = res * a % mod;
    		a = a * a % mod;
    	}
    	return res % mod;
    }
    
    inline lxl Fermat_inv(lxl a,lxl mod){
    	return Quick_Pow(a,mod-2,mod);
    } 
    
    inline void calc() {
    	fac[0] = 1;//¹æ¶¨0!=1
    	int t=MX-5;
    	rep(i, 1, t) 
    		fac[i] = (fac[i - 1] * i) % mod;
    	inv_fac[t] = Fermat_inv(fac[t], mod);
    	drp(i, t-1, 0) 
    		inv_fac[i] = inv_fac[i + 1] * (i + 1) % mod;
    }
    
    inline lxl C(lxl r,lxl n){
    	if(n==0) return 1;
    	return fac[n]*inv_fac[r]%mod*inv_fac[n-r]%mod;
    }
    
    int main() {
    	freopen("chess.in", "r", stdin);
    	freopen("chess.out", "w", stdout);
    	int T;
    	calc();
    	read(T);
    	while(T--) {
    		read(n);
    		read(m);
    		if(m == 1) {
    			out(n);
    			continue;
    		}
    		ans =(( C(m,n+m) )%mod-1+mod)%mod;
    		out(ans);
    	}
    	return 0;
    }
    

    本文来自博客园,作者:{2519},转载请注明原文链接:https://www.cnblogs.com/QQ2519/p/15120491.html

  • 相关阅读:
    CentOS查看CPU信息、位数、多核信息
    Linux常用命令大全
    chmod命令详细用法
    tar命令的详细解释
    yum和rpm命令详解
    LeetCode 241. Different Ways to Add Parentheses
    LeetCode 139. Word Break
    LeetCode 201. Bitwise AND of Numbers Range
    LeetCode 486. Predict the Winner
    LeetCode 17. Letter Combinations of a Phone Number
  • 原文地址:https://www.cnblogs.com/QQ2519/p/15120491.html
Copyright © 2011-2022 走看看