2017年CCPC杭州现场赛 Master of Phi (优化二进制枚举子集)

一直感觉枚举子集这种没啥可优化的,直到遇到这题,这题对时间卡的比较死,枚举子集其实是可以写的,但是双层 f o r for for 的枚举子集的复杂度是 2 n 2^n 2n ∗ * n n n,这题是 T = 100 T=100 T=100 组输入, n < = 20 n<=20 n<=20,然后我们可以推出贡献可以由枚举子集得到,但是这样最坏的时间复杂度是 O O O( 2 2 2 2 ^2 2 0 ^0 0 ∗ 20 *20 20 ∗ 100 *100 100) > O ( 3 e 8 ) O(3e8) O(3e8),所以我们可以用完全二叉树形式的 d f s ( ) dfs( ) dfs() 来优化二进制的枚举子集,这个东西还是今天一个老师在课堂上问我 b f s ( ) bfs() bfs()形式的 01 01 01 背包,我所学会的,显然 b f s ( ) bfs( ) bfs() 或者 d f s ( ) dfs( ) dfs() 01 01 01 背包的实质就是枚举子集。

参考代码

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <vector>
using namespace std;
typedef long long ll;
const int maxn = 1e6 + 5;
const int mod = 998244353;
void read(int& v) {
    
    
  int k = 1;
  v = 0;
  int c = getchar();
  while (c < '0' || c > '9') {
    
    
    if (c == '-')
      k = 0;
    c = getchar();
  }
  while (c >= '0' && c <= '9')
    v = (v << 3) + (v << 1) + (c - 48), c = getchar();
  if (k == 0)
    v = -v;
}
inline ll ksm(ll a, ll b) {
    
    
  ll res = 1;
  while (b) {
    
    
    if (b & 1)
      res = res * a % mod;
    b >>= 1, a = a * a % mod;
  }
  return res;
}
int pn[25], ps[25];
int pm[25], pos[(maxn + 50000) * 4];
void init() {
    
    
  for (int i = 1; i <= 1048576; i++)
    pos[i] = log2(i) + 1;
}
ll ans;
inline void dfs(int k, int l, int r, int w, ll sum) {
    
    
  int i = pos[k];
  if (l == r) {
    
    
    ans = (ans + sum) % mod;
    return;
  }
  int mid = (l + r) >> 1;
  dfs(k << 1, l, mid, 0, sum);
  dfs(k << 1 | 1, mid + 1, r, 1, ((sum * ps[i]) % mod) * pm[i] % mod);
}
int main() {
    
    
  init();
  int t;
  read(t);
  while (t--) {
    
    
    int n;
    read(n);
    ll sum = 1;
    for (int i = 1; i <= n; i++) {
    
    
      read(pn[i]), read(ps[i]);
      sum = (sum * ksm(pn[i], ps[i])) % mod;
      pm[i] = (pn[i] - 1ll) * ksm(pn[i], mod - 2) % mod;
    }
    ans = 0;
    dfs(1, 1, (1 << n), 0, 1);
    printf("%lld\n", ans * sum % mod);
  }
}

猜你喜欢

转载自blog.csdn.net/yangzijiangac/article/details/109629375
phi