HDU 6425(羽毛球组合 **)

题意是说有四种同学,没有球拍没有球的( a ),只有球拍的( b ),只有球的( c ),既有球拍又有球的( d );现在要去打羽毛球,每个人都可以选择去或者不去,问有多少种无法打羽毛球的情况。

无法打羽毛球的原因可以分成:球不够或球拍不够。

这样分不是很清楚,改成:只是球不够,只是球拍不够,球和球拍都不够。

先看第一种:只是球不够。球只需要一颗就够了,也就是说有球的同学都不去,同时有球拍的同学至少去两位,情况数:2^b - C(b,1) - C(b,0);

再看第二种:只是球拍不够。带球的同学至少去一位,带球拍的同学最多去一位,情况数:( C(b,1) * (2^c - 1) ) + ( C(d,1) * 2^c ) + ( 2^c - 1 );

再看第三种:球和球拍都不够。带球的同学都不去,带球拍的同学最多去一位,情况数:b + 1;

由于第一种同学是什么都没有的,所以对球数和球拍数不会造成影响,可以直接在上述三种情况数求和的基础上使用乘法原理,即乘以 ( 2^a )即可。

这道题的数量级比较大,要注意不停地取模,否则会超出 long long 的存储范围。

代码如下:

 1 #include <cstdio>
 2 #include <cmath>
 3 #include <algorithm>
 4 using namespace std;
 5 const __int64 mod = 998244353;
 6 __int64 a,b,c,d,wu,aa,bb,cc;
 7 __int64 quickpow(__int64 n)
 8 {
 9     if(n==1) return 2;
10     else if(n==0) return 1;
11     if(n&1) return (quickpow(n>>1)%mod*(quickpow(n>>1)%mod)*2)%mod;
12     return (quickpow(n>>1)%mod*(quickpow(n>>1)%mod))%mod;
13 }
14 int main()
15 {
16     int t;
17     scanf("%d",&t);
18     while(t--)
19     {
20         scanf("%I64d%I64d%I64d%I64d",&a,&b,&c,&d);
21         aa = quickpow(a);
22         bb = quickpow(b);
23         cc = quickpow(c);
24         //printf("%I64d %I64d %I64d
",aa,bb,cc);
25         wu = (aa%mod*((bb-1-b)%mod+((b+d+1)%mod*(cc%mod))%mod))%mod;
26         printf("%I64d
",wu);
27     }
28     return 0;
29 }
View Code
日后若能有更好的想法,再来完善。 希望看到的大神不吝赐教 orz
原文地址:https://www.cnblogs.com/Taskr212/p/9508012.html