题意:a个人没有拍子和羽毛球,b个人有拍无球,c个人有球无拍,d个人有球有拍,问不能组成游戏的有多少可能(要组成游戏即是要至少两个拍子以及1个球)
思路:我们知道要不能组成游戏即
X=0,X=1(拍子数) ;Y=0(球数). 组合下来就是 (X,Y) : (0,0) (0,N) (1,N) (N,0) ,同时还要减去重复的问题
然后每个人由参加和没有参加的状态两种所以就是 1<<n (2^n) :
理解1: (0,N) 2^(a+c): (1,N) (b+d)*2^(a+c);考虑b类型和d类型的人中来了1个其余任意组合 (N,0)2^(a+b) 去重:在(0,N)(N,0)组成中包含了(0,0)的情况即所以要减去 2^a ; (1,N)中包含了 (1,0)情况 与(N,0)中包含的情况重合所以减去 b*2^(a) 所以最后: 2^(a+c) + (b+d)*2^(a+c) + 2^(a+b) - 2^a - b*2^(a) = 2^a *(2^c + 2^c*(b+d)+2^b-1-b*2^a) = 2^a(1 + (2^b-1) + (2^c-1) *(b+d+1) + d); 理解2: 由于a参加不影响: (1) (0,0) b,c,d都不参加 2^a (2) (N,0) 2^(a+b) 但是和 (0,0)有重复所以减 -> 变成 2^(a+b)-2^a (3) (0,N) 同理: 2^(a+c) - 2^a (4) (1,N) : (0+1,N) 选一个b不选d :b*(2^(a+c) -2^a) , (0+1,1+N) 选一个d不选b :d*(2^(a+c)-2^a); (5) (1,1) :上面不包含: 之选一个d不选c : d*2^a 所以总式子:2^a(1 + (2^b-1) + (2^c-1) *(b+d+1) + d);
完整代码:
////关于位运算处理问题,虽然也能求(2^n)但是由于有取模问题(在位移中就可能出现超出mod范围而没有取模的问题) //int main(){ // ios_base::sync_with_stdio(0); // cin.tie(0); // int n; // cin>>n; // while(n--){ // ll a,b,c,d; // cin>>a>>b>>c>>d; // ans = 0; // ans = (1<<a)%mod*(1+((1<<b)-1)%mod+(((1<<c)-1)%mod*(b+d+1)%mod)%mod+d)%mod; // printf("%lld\n",ans); // } //} #include <iostream>
#include <cstdio>
#define mod 998244353
#define ll long long
using namespace std;
ll qpow(ll a, ll b){ int ans = 1; a = a % mod; while(b){ if(b&1)ans = (ans * a) % mod; a = (a * a) % mod; b >>= 1; } return ans%mod; } int main() { int T; ll a, b, c, d;
ll ans; scanf("%d",&T); while(T--) { scanf("%lld%lld%lld%lld",&a,&b,&c,&d);
ans = qpow(2,a)%mod*(1+(qpow(2,b)-1)%mod+((qpow(2,c)-1)%mod*(b+d+1)%mod)%mod+d)%mod; printf("%lld\n",ans); } return 0; }