zoukankan      html  css  js  c++  java
  • [AcWing 569-猜拳游戏] 快速求组合数的方法

    [AcWing 569-猜拳游戏] 快速求组合数的方法
    题目链接:AcWing 569-猜拳游戏
    小Q和牛妹参加一个剪刀石头布的游戏,游戏用卡片来玩,每张卡片是剪刀,石头,布中的一种,每种类型的卡片有无限个。

    牛妹从中选了n张卡片排成一排,正面朝下,小Q也会选择n张卡片排成一排,然后小Q和牛妹的卡片会依次进行比对,第一张对第一张,第二张对第二张…

    如果小Q赢,小Q会得到一分,现在已知牛妹的每一张牌以及小Q最终的得分 s,请问小Q有多少种选择卡片的方案(多少不同的排列)
    输入格式

    第一行包含两个整数 n 和 s。

    第二行包含 n 个整数,表示牛妹的每张卡片,每个数在[0,2]之间,0代表石头,1代表布,2代表剪刀。
    输出格式

    输出一个整数,表示总方案数对109+7

    取模后的值。
    数据范围

    1≤n≤2000
    ,
    0≤s≤2000

    输入样例:

    3 2
    0 1 2

    输出样例:

    6

    这个题有个小坑,就是第二行的输入没有什么用,就是来干扰你的;分析清楚后就是一个求组合数的问题
    思路简单:
    1.先在n中选s个,作为必赢的方案,即Cns;
    2.剩下的n-s有两种选择,即2n-s
    3.总的方案就是Cns 2n-s*

    但是如果直接用公式Cns=Cn-1s+Cn-1s-1或者带n!/(s!*(n-s)!)都会爆,或者太费时
    所以这里重要的如何去求Cns;
    大概思路就是:

    1.先把n里面所有的素数找出来(因为下面要进行质因数分解)
    2.对于每个数都可以写成以素数为底,任意次方的乘积形式.如12=2231
    3.所以我们可以先对分子n!和分母s!
    (n-s)!进行约分,因为都有可能出现相同的底数
    4.所以我们就去找同一个底数,分子和分母分别出现的次数,然后用分子-分母(即约分操作),这里有个简单的技巧去求N!中某个数p出现的次数cnt=(N/p)+(N/p2)+(N/p3)+(N/p4)+…+;
    5.计算出所有底数(出现的次数)的乘机,然后再计算出2n-s,然后两者相乘即可

    代码

    #include<iostream>
    using namespace std;
    const int N=1e5+5,mod=1e9+7;
    int  primes[N],cnt, m,n,a;
    bool vis[N];
    //获取0~N所有的素数
    void get_primes(int N) {
    	for(int i=2; i<=N; i++) {
    		if(!vis[i]) {
    			primes[cnt++]=i;
    			for(int j=i+i; j<=N; j+=i) {
    				vis[j]=true;
    			}
    		}
    	}
    }
    //返回n的阶乘里面包含几个p
    int get_numberOF(int n,int p) {
    	int res=0;
    	while(n) {
    		res+=n/p;
    		n/=p;
    	}
    	return res;
    }
    //计算a的b次幂,结果对mod取余
    long long fastPower(int a,int b,int mod) {
    	long long res=1;
    	while(b) {
    		if(b&1) {
    			res=res*a%mod;
    		}
    		b>>=1;
    		a=(long long)a*a%mod;
    	}
    	return res;
    }
    int main() {
    	cin>>m>>n;
    	get_primes(m);
    	int power,ans=fastPower(2,m-n,mod);//先计算2的m-n次方 
    	for(int i=0; i<cnt; i++) {
    		power=get_numberOF(m,primes[i])-get_numberOF(n,primes[i])-get_numberOF(m-n,primes[i]);//计算出剩下的次方数
    		ans= ans*fastPower(primes[i],power,mod) %mod;
    	}
    	cout<<ans<<endl;
    	return 0;
    }
    
  • 相关阅读:
    python
    weui 问题
    Mac 问题
    ORM存储过程和实体类代码生成工具
    说说QQ空间SEO
    用户体验走嘴和走心的区别
    一切不以用户为中心的O2O 都是耍流氓
    10分钟制作自己的手机QQ
    一无所有其实没什么
    别人的鞋不一定合脚
  • 原文地址:https://www.cnblogs.com/zdw20191029/p/14553386.html
Copyright © 2011-2022 走看看