1. 程式人生 > >sincerit Protoss and Zerg(快速冪求組合)

sincerit Protoss and Zerg(快速冪求組合)

連結:https://ac.nowcoder.com/acm/contest/303/H
來源:牛客網

題目描述
1v1,是星際爭霸(StarCraft)中最常見的競技模式。

tokitsukaze進行了n場1v1。在每一場的1v1中,她都有星靈(Protoss)和異蟲(Zerg)兩個種族可以選擇,分別有a個單位和b個單位。因為tokitsukaze不太擅長玩人類(Terran),所以她肯定不會選擇人類。

對於每一場1v1,玩家只能控制己方單位。也就是說,如果選擇蟲族,那麼只能控制蟲族單位,如果玩家選擇星靈,那麼只能控制星靈單位。

在n場1v1中,假設第i場,有ai個蟲族單位,和bi個星靈單位。tokitsukaze可以在一場1v1中,任選一種種族進行遊戲。如果選擇了蟲族,那麼在這場遊戲中,可以選擇出兵1到ai個單位。那麼同理,如果選擇了星靈,那麼在這場遊戲中,可以選擇出兵1到bi個單位。

假設所有異蟲單位互不相同,所有星靈單位也互不相同,那麼請問tokitsukaze打完這n場1v1,出兵的總方案數是多少,由於答案很大,所以輸出答案mod 998244353 後的結果。

注意:若兩個方案,有其中一個單位不同,即視為不相同。

輸入描述:
第一行包含一個T(T≤10),表示T組資料。

對於每組資料:
第一行包含一個正整數n(1≤n≤100000)。
接下來n行,第i行包含兩個整數ai,bi(1≤ai,bi≤10^9),表示第i場1v1,有ai個異蟲單位,和bi個星靈單位。
輸出描述:
對於每組資料,輸出一行,表示mod 998244353後的答案。
示例1
輸入
複製
1
2
1 2
2 1
輸出
複製
16
說明
第一組樣例:

對於第一場對局,tokitsukaze可以選擇的蟲族兵種有一個,並且將其編號為1,tokitsukaze可以選擇的星靈兵種有兩個,將其編號為1,2。所以tokitsukaze有四種可供選擇的遊戲方案:

1、選擇蟲族,並且派出蟲族1號兵種。
2、選擇星靈族,並且派出星靈族1號兵種。
3、選擇星靈族,並且派出星靈族2號兵種。
4、選擇星靈族,並且派出星靈族1,2號兵種。

對於第二場對局,tokitsukaze可以選擇的蟲族兵種有兩個,並且將其編號為1,2,tokitsukaze可以選擇的星靈兵種有一個,將其編號為1。所以tokitsukaze有四種可供選擇的遊戲方案:
1、選擇蟲族,並且派出蟲族1號兵種。
2、選擇蟲族,並且派出蟲族2號兵種。
3、選擇蟲族,並且派出蟲族1,2號兵種。
4、選擇星靈族,並且派出星靈族1號兵種。

兩場對局是相互獨立的事件,所以兩輪遊戲的出兵方案總數為4*4(mod 998244353)=16種。

假設要派出的兵種有n種
那麼可以有多少種組合呢, 可以看成有n個人,每個人都有兩種選擇(被派出和不被派出)
那麼就有2^n這麼多種組合情況,除去一個全部不派出的情況就保證了至少有一個人被派出
所以就有2^n-1種情況

#include <stdio.h>
#include <cstring>
typedef long long ll;
const ll MOD = 998244353;
const ll N = 1e5 + 5;
ll spow(ll x, ll n) {
  x %= MOD;
  ll ans = 1;
  while (n) {
    if (n&1) ans = (ans * x) % MOD;
    n >>= 1;
    x = (x * x) % MOD;
  }
  return ans%MOD;
}
int main() {
  int t;
  scanf("%d", &t);
  while (t--) {
    ll n, a, b;
    scanf("%lld", &n);
    ll ans = 1, sum = 0;
    for (int i = 1; i <= n; i++) {
      scanf("%lld %lld", &a, &b);
      a = spow(2, a) - 1;
      b = spow(2, b) - 1;
      ans = (ans * (a+b)) % MOD;
    }
    printf("%lld\n", ans);
  }
  return 0;
}