专栏文章

Solution:P11897 「LAOI-9」多维空间中的游戏

P11897题解参与者 4已保存评论 3

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
3 条
当前快照
1 份
快照标识符
@mipwfghu
此快照首次捕获于
2025/12/03 19:03
3 个月前
此快照最后确认于
2025/12/03 19:03
3 个月前
查看原文
以下 nn 代表原题面中的 kk
首先这个游戏显然就是当 popcount(ab)\operatorname{popcount}(a\cup b) 为奇数时先手必胜。也就是说题目的意思是我们要对 0a<2n0\leq a<2^n
1i=lr[popcount(ai)1(mod2)]pi=112i=lrpi(1)npopcount((2n1a)(2n1i))pi1-\sum_{i=l}^{r}[\operatorname{popcount}(a\cup i)\equiv 1\pmod 2]p_i=1-\frac 12\sum_{i=l}^{r}p_i-(-1)^{n-\operatorname{popcount}((2^n-1-a)\cap (2^n-1-i))}p_i
显然后面那个东西就是 xor-FWT 的定义式,也就是说我们只要只保留 p2n1r2n1lp_{2^n-1-r\sim 2^n-1-l} 然后做 FWT 就完事了,时间复杂度 O(nq2n)\Omicron(nq2^n)
然后我们发现这个东西被卡常了过不去。首先加个fread,接下来我们注意两个地方:
  • FWT 的过程中不要取模。
  • 可以发现,FWT 每做一层只有一个区间是有值的,那么如果我们当前遍历到的区间没有值就直接跳过。
这样就能做到最大点在 1.4s 内通过。
注意以下代码做的其实是 xnor-FWT。
CPP
#include <algorithm>
#include <iostream>
#include <vector>
#include <bitset>
#include <string>
#include <array>

#define rgall(arr) (arr).begin(),(arr).end()
#define rgcnt(arr,cnt) (arr).begin(),(arr).begin()+(cnt)
#define rgo1(arr,cnt) (arr).begin()+1,(arr).begin()+1+(cnt)
#define rgany(arr,cnt,offset) (arr).begin()+(offset),(arr).begin()+(offset)+(cnt)

using namespace std;

inline char nc()
{
	static char buf[100000],*p1=buf,*p2=buf;
	return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline int reader()
{
	char ch=nc();
	int sum=0;
	int flag=1;
	while(!(ch>='0'&&ch<='9'))
	{
		if(ch=='-')flag=-1;
		ch=nc();
	}
	while(ch>='0'&&ch<='9')
		sum=sum*10+ch-48,ch=nc();
	return sum*flag;
}

constexpr int moder=998244353,inv_2=moder+1>>1,neg_1=moder-1;

inline int fast_mod(int x)
{
    return x-(x>=moder?moder:0);
}

array<long long,1<<16> vals,val0;

int main(int argc,char* argv[],char* envp[])
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int outflag;
    unsigned int seed;
    reader(),outflag=reader();
    if(outflag)
        seed=reader();
        // cin>>seed;
    int n=reader();
    // cin>>n;
    const int S=(1<<n)-1;
    for(int i=0;i<1<<n;i++)
        vals[i]=reader();
    int cntq=reader();
    // cin>>cntq;
    for(int q=1;q<=cntq;q++)
    {
        int cntq0,rgl,rgr;
        // cin>>cntq0>>rgl>>rgr;
        cntq0=reader(),rgl=reader(),rgr=reader();
        val0.fill(0);
        long long sum=0;
        for(int i=rgl;i<=rgr;i++)
            sum+=val0[i]=vals[i];
        for(int i=1,curl=rgl,curr=rgr;i<1<<n;curl-=i,curr+=i,i<<=1)
        {
            for(int j=0;j<1<<n;j+=i<<1)
            {
                if(j>curr||j+i+i<curl)
                    continue;
                for(int k=0;k<i;k++)
					val0[i|j|k]=-val0[j|k]-val0[i|j|k],val0[j|k]=val0[i|j|k]+val0[j|k]*2;
            }
            // for(int i=0;i<1<<n;i++)
            //     cerr<<val0[i]<<' ';
            // cerr<<endl;
        }
        int answer=0;
        for(int i=1;i<=cntq0;i++)
        {
            int a;
            if(outflag)
                a=seed*i*q*50007&S;
            else
                a=reader();
                // cin>>a;
            a=(1-(sum-val0[a])/2%moder+moder)%moder;
            if(outflag)
                answer^=a;
            else
                cout<<a<<' ';
        }
        if(outflag)
            cout<<answer;
        cout<<'\n';
    }
    return 0;
}

评论

3 条评论,欢迎与作者交流。

正在加载评论...