题意是说有四种同学,没有球拍没有球的( 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 }