【组合数+全错排】fzuoj 2282 Wand
来源:互联网 发布:北京可以备案的域名 编辑:程序博客网 时间:2024/06/05 06:24
Accept: 31 Submit: 95
Time Limit: 1000 mSec Memory Limit : 262144 KB
Problem Description
N wizards are attending a meeting. Everyone has his own magic wand. N magic wands was put in a line, numbered from 1 to n(Wand_i owned by wizard_i). After the meeting, n wizards will take a wand one by one in the order of 1 to n. A boring wizard decided to reorder the wands. He is wondering how many ways to reorder the wands so that at least k wizards can get his own wand.
For example, n=3. Initially, the wands are w1 w2 w3. After reordering, the wands become w2 w1 w3. So, wizard 1 will take w2, wizard 2 will take w1, wizard 3 will take w3, only wizard 3 get his own wand.
Input
First line contains an integer T (1 ≤ T ≤ 10), represents there are T test cases.
For each test case: Two number n and k.
1<=n <=10000.1<=k<=100. k<=n.
Output
For each test case, output the answer mod 1000000007(10^9 + 7).
Sample Input
Sample Output
Source
第八届福建省大学生程序设计竞赛-重现赛(感谢承办方厦门理工学院)题意:n个巫师对应n个魔法棒,问让至少k个巫师拿对自己的魔法棒有多少种重排方案;
思路:从n中选k个组合,剩下n-k个全错排;全错排公式:a[i]=(i-1)*(a[i-1]+a[i-2]); 相同思路的题目nyoj451光棍节的快乐
代码1:
#include<cstdio>#include<cstring>#include<algorithm>using namespace std;#define mod 1000000007const int maxn=10004;typedef long long ll;ll f[maxn+10];ll fac[maxn+10];void init(){ fac[0]=1,fac[1]=1,fac[2]=2; //预处理阶乘 for(ll i=3;i<=maxn;i++) { fac[i]=(fac[i-1]*i*1LL)%mod; fac[i]%=mod; }}ll inv(ll a) //求a对mod的逆元{ return a==1?1:inv(mod%a)*(mod-mod/a)%mod;}ll C(ll n,ll m) //组合数{ return fac[n]*inv(fac[m])%mod*inv(fac[n-m])%mod;}int main(){ int T; f[0]=1,f[1]=0,f[2]=1,f[3]=2; for(ll i=4;i<=maxn;i++) { f[i]=(i-1)*((f[i-1]%mod+f[i-2]%mod)%mod); f[i]%=mod; } init(); scanf("%d",&T); while(T--) { ll n,k; scanf("%I64d%I64d",&n,&k); ll res=0; for(int i=k;i<=n;i++) { ll res1=C(n,i)%mod; ll res2=f[n-i]%mod; // printf("%I64d %I64d\n",res1,res2); res+=(res1*res2)%mod; res%=mod; } printf("%I64d\n",res); } return 0;}//耗时109ms
#include<cstdio>#include<cstring>#include<algorithm>using namespace std;#define mod 1000000007const int maxn=10004;typedef long long ll;ll f[maxn+10],inv[maxn+10];ll fac[maxn+10];ll mod_pow(ll x,ll n){ ll res=1; while(n>0) { if(n&1) res=res*x%mod; x=x*x%mod; n>>=1; } return res%mod;}void init(){ fac[0]=1,fac[1]=1,fac[2]=2; for(ll i=3;i<=maxn;i++) { fac[i]=(fac[i-1]*i*1LL)%mod; fac[i]%=mod; } inv[maxn]=mod_pow(fac[maxn],mod-2); //预处理阶乘的逆元 for(ll i=maxn-1;i>=0;i--) inv[i]=(inv[i+1]*(i+1))%mod;}ll C(ll n,ll m){ return fac[n]*inv[m]%mod*inv[n-m]%mod;}int main(){ int T; f[0]=1,f[1]=0,f[2]=1,f[3]=2; for(ll i=4;i<=maxn;i++) { f[i]=(i-1)*((f[i-1]%mod+f[i-2]%mod)%mod); f[i]%=mod; } init(); scanf("%d",&T); while(T--) { ll n,k; scanf("%I64d%I64d",&n,&k); ll res=0; for(int i=k;i<=n;i++) { ll res1=C(n,i)%mod; ll res2=f[n-i]%mod;// printf("%I64d %I64d\n",res1,res2); res+=(res1*res2)%mod; res%=mod; } printf("%I64d\n",res); } return 0;}//耗时0ms
*因为须对1e9+7取模,所以可以先预处理阶乘数组fac[ ],阶乘的线性逆元inv[ ],如果每次都求一下c(n,i)的话,复杂度位O(n^2);
*另外求组合数是fac[n]/fac[m]/fac[n-m]这样的话,会爆精度,应该变除为乘,乘以所要除的数的逆元,所以先预处理一波阶乘的逆元;
*代码2比代码1高效在于预处理阶乘的线性逆元,预处理代码是学习别人的;
- 【组合数+全错排】fzuoj 2282 Wand
- FZUOJ 2282 Wand
- FZU 2282 Wand 【组合数学】
- FZU 2282 Wand(组合)
- FZU 2282 Wand (组合数学 错排应用)
- 【FZUOJ 2020】 组合
- 第八届福建省大学生程序设计竞赛 K.Wand【错排+组合数】
- 第八届福建省大学生程序设计竞赛-K Wand(错位+组合数)
- fzu 2282 Wand
- [FZUOJ
- FZUoj 2020 组合 (组合数学&&Lucas定理)
- FZU 2282 Wand(错排+费马小定理)
- FZU 2282 Wand(错排+费马小定理)
- 组合数
- 组合数
- 组合数
- 组合数
- 组合数
- 组合数取模(sdut3895+HDU3037)逆元法或Lucas
- IO流小结
- HDU2548 两军交锋【数学计算+水题】
- openstack之malina学习
- 三角形 oj62
- 【组合数+全错排】fzuoj 2282 Wand
- 使用vue cli开发项目中遇到的坑
- C#设计模式(九)装饰者模式(Decorator Pattern)
- Java_基础—flush和close方法的区别
- Java类加载机制
- 调用https接口的工具类
- 46
- 47
- 【数组的距离】 oj65