Gym - 101775A Chat Group 组合数+逆元+快速幂
It is said that a dormitory with 6 persons has 7 chat groups ^_^. But the number can be even larger: since every 3 or more persons could make a chat group, there can be 42 different chat groups.
Given N persons in a dormitory, and every K or more persons could make a chat group, how many different chat groups could there be?
Input
The input starts with one line containing exactly one integer T which is the number of test cases.
Each test case contains one line with two integers N and K indicating the number of persons in a dormitory and the minimum number of persons that could make a chat group.
- 1 ≤ T ≤ 100.
- 1 ≤ N ≤ 109.
- 3 ≤ K ≤ 105.
For each test case, output one line containing "Case #x: y" where x is the test case number (starting from 1) and y is the number of different chat groups modulo 1000000007.
Example1
6 3
Case #1: 42
题解:
看起来很简单的题 我还是做了很久 基础知识点有很多漏洞吧
本题就是一个 C(n,k)+C(n,k+1)+...+C(n,n) 的过程
如果暴力算的话会超时 哭叽叽
要知道组合数的总和是2^n
所以转化成 2^n - C(n,0)+C(n,1)+...+C(n,k-1)
加减乘可直接用同余定理直接拆开算 除法不行
所以利用费马小定理(假如p是质数,且gcd(a,p)=1,那么 a(p-1)≡1(mod p),即:假如a是整数,p是质数,且a,p互质(即两者只有一个公约数1),那么a的(p-1)次方除以p的余数恒等于1。)
得到推论 a*a(p-2)≡1(mod p)对于整数a,p,a关于p的逆元就是a^(p-2),直接快速幂解之即可,但注意这个定理要求a,p互质
利用上述方法求得逆元
计算乘方时用到快速幂
如此这一问题便解决了
(我的第一篇博客,欢迎大家批评指正^-^)
#include <iostream> #include <stdio.h> using namespace std; typedef long long ll; const int N=1e5+7; const ll mod=1e9+7; ll quick(ll a,ll b) //快速幂 { ll ans=1; a%=mod; while(b){ if(b&1) ans=ans*a%mod; a=a*a%mod; b>>=1; } return ans; } int main() { ll n,k,i; int l=1,t; scanf("%d",&t); while(t--){ scanf("%I64d%I64d",&n,&k); ll ans=quick(2,n)-1; //2^n-C(n,0) ll cur=n; for(i=1;i<k;i++){ ans=(ans+mod-cur)%mod; //emmm 为啥要加个mod我还不太了解,如果有大佬知道,麻烦指点一下 cur=cur*(n-i)%mod; cur=cur*quick(i+1,mod-2)%mod; //乘以逆元 } printf("Case #%d: %I64d\n",l++,ans); } return 0; }