NOIP模拟赛 篮球比赛2
篮球比赛2(basketball2.*)
由于Czhou举行了众多noip模拟赛,也导致放学后篮球比赛次数急剧增加。神牛们身体素质突飞猛进,并且球技不断精进。这引起了体育老师彩哥的注意,为了给校篮球队找到势均力敌的对手,彩哥找到了Czhou神,想要和机房篮球队进行多场友谊赛。Czhou为了顾全校篮球队面子,决定派出配合默契又不至于吊打校篮球队的阵容。
而机房神牛的能力值受到游戏时长,训练时长,个人基础值得影响,可能会不断变化。所以Czhou想根据神牛当天状态从中选出若干名选手,使他们的能力值和等于k。
Input: basketball2.in
一行三个数n,k,l。表示机房有n个神牛,选出队员能力值和为k,每个神牛的能力最大值<=L且>=0。
Ouput:basketball2.out
输出一个数,表示方案数,方案满足选出若干选手使能力和为k。因为答案比较大,最后模10^9+7。
Sample.in
2 2 2
Sample.out
6
样例说明:神牛的能力值可能为(0,2)(1,2)(1,1)(2,0)(2,1)(2,2),这样都可以选出一些数字使他们的能力值和为2。
对于(0,2)表示第一只牛能力值为0,第二只牛能力为2
类似的
对于(1,2)选出2即满足要求。
对于(1,1)选出全部选手即满足要求。
所以(0,2)(1,1)都是满足要求的方案。
数据范围:
n,k<=20
0<=L<=10^9.
1 #include<iostream> 2 using namespace std; 3 4 const int mod=1000000007; 5 6 int N,K,L; 7 long long F[21][1048576];//二进制存储,不得不佩服hzwer学长的能力 8 int ed,ans; 9 10 int read() 11 { 12 int x=0,f=1;char ch=getchar(); 13 while(ch<='0'||ch>='9') {if(ch=='-') f=-1;ch=getchar();} 14 while(ch>='0'&&ch<='9') 15 { 16 x=x*10+ch-'0'; 17 ch=getchar(); 18 } 19 return x*f; 20 } 21 22 int main() 23 { 24 N=read();K=read();L=read(); 25 ed=(1<<K)-1; 26 for(int i=0;i<min(K,L);i++) 27 F[1][1<<i]=1; 28 if(K<=L) F[1][0]=L-K+1; 29 for(int i=1;i<N;i++) 30 { 31 F[i][0]=max(F[i][0],(long long)1); 32 for(int j=0;j<=ed;j++) 33 if(F[i][j]) 34 { 35 for(int k=0;k<=min(K,L);k++) 36 { 37 int to=((j<<k)|j|(1<<(k-1)))&ed;//这里很不好理解,实际上就是i+j能取到的,和j本身取到的,以及k本身取到的,最后&ed限制范围 38 F[i+1][to]=(F[i+1][to]+F[i][j])%mod; 39 } 40 if(K<=L) F[i+1][j]=(F[i+1][j]+F[i][j]*(L-K))%mod; 41 } 42 } 43 for(int i=0;i<=ed;i++) 44 if(i&(1<<(K-1))) 45 ans=(ans+F[N][i])%mod; 46 cout<<ans<<endl; 47 return 0; 48 }