zoukankan      html  css  js  c++  java
  • 牛客挑战赛36 G Nim游戏(分治FWT)

    https://ac.nowcoder.com/acm/contest/3782/G

    题解:

    分治FWT裸题。

    每个都相当于((1+b[i]x^{a[i]})),求这玩意的异或卷积。

    先把a[i]相同的并在一起。

    考虑分治,一个区间内的数的二进制的前若干位是相同的,所以只需要记录这个区间的数选了奇数还是偶数个以及后面的二进制位每一个异或结果的系数。

    考虑合并,两个子区间二进制位上只有一个不同,那么右区间用了奇数个的话,这一位+1就好了。

    写递归似乎常数比较大。

    Code:

    #include<bits/stdc++.h>
    #define fo(i, x, y) for(int i = x, _b = y; i <= _b; i ++)
    #define ff(i, x, y) for(int i = x, _b = y; i <  _b; i ++)
    #define fd(i, x, y) for(int i = x, _b = y; i >= _b; i --)
    #define ll long long
    #define pp printf
    #define hh pp("
    ")
    using namespace std;
    
    #define gc getchar
    template<class T> void read(T &x) {
    	char c = ' '; x = 0;
    	while(c < '0' || c > '9') c = gc();
    	for(; c >= '0' && c <= '9'; c = gc()) x = x * 10 + c - '0';
    }
    
    const int mo = 998244353;
    
    ll ksm(ll x, ll y) {
    	ll s = 1;
    	for(; y; y /= 2, x = x * x % mo)
    		if(y & 1) s = s * x % mo;
    	return s;
    }
    
    const int N = 131072;
    
    
    int n, x, y;
    ll f[N][2], a[N], b[N];
    
    void fwt(ll *a, int n, int f) {
    	ll b;
    	for(int i = 1; i < n; i *= 2) for(int j = 0; j < n; j += 2 * i) ff(k, 0, i)
    		b = a[i + j + k], a[i + j + k] = a[j + k] - b, a[j + k] += b;
    	ff(i, 0, n) a[i] %= mo;
    	if(f == -1) {
    		b = ksm(n, mo - 2);
    		ff(i, 0, n) a[i] = a[i] * b % mo;
    	}
    }
    
    ll g[N][2];
    
    void dg(int x, int y) {
    	if(x == y) return;
    	int m = x + y >> 1;
    	dg(x, m); dg(m + 1, y);
    	int n = y - m;
    	fo(k, x, y) g[k][0] = g[k][1] = 0;
    	fo(i, 0, 1) fo(j, 0, 1) {
    		fo(k, x, m) a[k - x] = f[k][i];
    		fo(k, m + 1, y) b[k - (m + 1)] = f[k][j];
    		fwt(a, n, 1); fwt(b, n, 1);
    		ff(k, 0, n) a[k] = a[k] * b[k] % mo;
    		fwt(a, n, -1);
    		ff(k, 0, n) g[x + k + j * (x ^ (m + 1))][i ^ j] += a[k];
    	}
    	fo(k, x, y) f[k][0] = g[k][0] % mo, f[k][1] = g[k][1] % mo;
    }
    
    int main() {
    	scanf("%d", &n);
    	ff(i, 0, N) f[i][0] = 1;
    	fo(i, 1, n) {
    		read(x); read(y);
    		ll f0 = f[x][0];
    		f[x][0] = (f[x][0] + f[x][1] * y) % mo;
    		f[x][1] = (f[x][1] + f0 * y) % mo;
    	}
    	dg(0, N - 1);
    	ll ans = (f[0][0] + f[0][1] - 1 + mo + mo) % mo;
    	pp("%lld
    ", ans);
    }
    
  • 相关阅读:
    实现对DataGird控件的绑定操作
    EasyUI-datagrid中load,reload,loadData方法的区别
    easui Pagination Layout
    easyUI datagrid 排序
    jQuery EasyUI教程之datagrid应用
    solr入门之多线程操作solr中索引字段的解决
    序列自相关矩阵的计算和分析
    UVa 12403
    滑动窗体的最大值(STL的应用+剑指offer)
    bzoj2101【Usaco2010 Dec】Treasure Chest 藏宝箱
  • 原文地址:https://www.cnblogs.com/coldchair/p/12374521.html
Copyright © 2011-2022 走看看