hdu6425 Rikka with Badminton

Problem Description

In the last semester, Rikka joined the badminton club.

There are n students in the badminton club, some of them have rackets, and some of them have balls. Formally, there are a students have neither rackets nor balls, bstudents have only rackets, c students have only balls, and d students have both rackets and balls. (a+b+c+d=n)

This week, the club is going to organize students to play badminton. Each student can choose to take part in or not freely. So there are 2n possible registration status. 

To play badminton, there must be at least two students who have rackets and at least one students who have balls. So if there aren't enough balls or rackets, the activity will fail. 

Now, Rikka wants to calculate the number of the status among all 2n possible registration status which will make the activity fail.

 

 

Input

The first line contains a single number t(1≤t≤103), the number of testcases.

For each testcase, the first line contains four integers a,b,c,d(0≤a,b,c,d≤107,a+b+c+d≥1).

Output

For each testcase, output a single line with a single integer, the answer modulo 998244353.

Sample Input

3

1 1 1 1

2 2 2 2

3 4 5 6

Sample Output

12

84

2904

题意:总共有n=a+b+c+d个人,其中a个人什么都没有,b个人有一个球拍,c个人有一个球,d个人有一个球与一个球拍。现要组织比赛,n个人每个人都可以参加或者不参加,那么总共的情况有2^n种,问2^n种方案中有多少种不符合要求。

解析

由于没有球,没有球拍都是不合法的,

首先考虑的是用没有球方案数加上没有球拍方案数,然后容斥减掉既没有求有没有求球拍的情况。

注意:对于球来说,0个球是不合法的;

          对于球拍来说0个或1个球拍都是不合法的;

答案首先加上以下3项:

  • ①.0个球的方案数为:2^(n-(c+d));即:手上有球的c+d个人都没来,而其余的n-(c+d)个人随意组合。
  • ②.0个球拍方案数为:2^(n-(b+d));即:手上有球拍的b+d个人都没来,而其余的n-(b+d)个人随意组合。
  • ③.1个球拍方案数为:(b+d)*2^(n-(b+d));考虑b类型和d类型的人中来了1个,其余n-(b+d)个人随意组合。

再减去以下2项重复的:

  • ④.0个球0个球拍的方案数:2^(n-(c+b+d));
  • ⑤.0个球1个球拍的方案数:b*2^(n-(c+b+d));b类型的人来了一个,c和d类型的人一个都没来,a类型任意来。

公式到此结束,

但是,一个球一个拍也是不合法的,这里,在加的时候我们在③将此种情况只算了一次,所以不用在容斥减的时候再减一遍。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll MAXN=1e5+5;
const ll mod=998244353;
 
ll a,b,c,d;
 
ll pow_mod(ll n,ll k,ll mod)//快速幂求n^k余m的结果
{
    ll res=1;
    n=n%mod;
    while(k>0)
    {
        if(k&1)
            res=res*n%mod;
        n=n*n%mod;
        k>>=1;
    }
    return res;
}
 
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%I64d%I64d%I64d%I64d",&a,&b,&c,&d);
        ll n=a+b+c+d;
        ll ans=pow_mod(2,n-(c+d),mod);                   //+①
 
        ans=(ans+(b+d+1)*pow_mod(2,n-(b+d),mod)%mod)%mod;//+②+③
 
        ans=(ans-(b+1)*pow_mod(2,n-(c+b+d),mod)%mod+mod)%mod;//-④-⑤
        printf("%I64d\n",ans);
    }
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值