题解 宇宙序列

传送门

补题解ing

首先FWT弄成对位相乘的形式
直接乘肯定不行,考虑倍增优化
康康怎么优化形如 \(b_i=\sum\limits_{j=0}^pa_i^{2^j}\) 的式子
\(f_{x, k}=\sum\limits_{j=0}^{2^k-1}x^{2^j}\)
注意这里的定义很巧妙,通过将上界减1省去了很多麻烦的边界问题,查询时直接将 \(p\) 加1就好了
转移截的skyh的image

点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 100010
#define ll long long
//#define int long long

char buf[1<<21], *p1=buf, *p2=buf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf, 1, 1<<21, stdin)), p1==p2?EOF:*p1++)
inline int read() {
	int ans=0, f=1; char c=getchar();
	while (!isdigit(c)) {if (c=='-') f=-f; c=getchar();}
	while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();}
	return ans*f;
}

int n, p, j;
const int mod=10007, inv2=5004;

namespace force{
	int a[1<<8][10];
	void solve() {
		int lim=1<<n;
		for (int i=0; i<lim; ++i) a[1][i]=read();
		for (int i=2; i<=(1<<p); ++i) {
			for (int j=0; j<lim; ++j) {
				for (int k=0; k<lim; ++k) {
					a[i][j]=(a[i][j]+a[i-1][k]*a[1][j^k])%mod;
				}
			}
		}
		int ans=0;
		for (int i=0; i<=p; ++i) ans=(ans+a[1<<i][j])%mod;
		printf("%d\n", ans);
	}
}

namespace task{
	int a[1<<18], b[1<<18], f[10007][30];
	inline int qpow(int a, int b, int mod=10007) {int ans=1; for (; b; a=a*a%mod,b>>=1) if (b&1) ans=ans*a%mod; return ans;}
	void fwt(int* a, int len, int op) {
		for (int i=1,x,y; i<len; i<<=1)
			for (int j=0,step=i<<1; j<len; j+=step)
				for (int k=j; k<j+i; ++k) {
					x=a[k], y=a[k+i];
					a[k]=(x+y)%mod;
					a[k+i]=(x-y)%mod;
					if (op==-1) a[k]=a[k]*inv2%mod, a[k+i]=a[k+i]*inv2%mod;
				}
		for (int i=0; i<len; ++i) a[i]=(a[i]+mod)%mod;
	}
	void solve() {
		int lim=1<<n; ++p;
		for (int i=0; i<lim; ++i) a[i]=read();
		for (int i=0; i<mod; ++i) f[i][0]=i;
		for (int i=1; i<30; ++i) for (int x=0; x<mod; ++x) f[x][i]=(f[x][i-1]+f[qpow(x, qpow(2, 1<<i-1, mod-1))][i-1])%mod; //, cout<<"f: "<<x<<' '<<i<<' '<<f[x][i]<<endl;
		fwt(a, lim, 1);
		for (int i=0; i<lim; ++i) for (int j=29; ~j; --j) if (p&(1<<j)) b[i]=(b[i]+f[a[i]][j])%mod, a[i]=qpow(a[i], qpow(2, 1<<j, mod-1));
		fwt(b, lim, -1);
		// cout<<"a: "; for (int i=0; i<lim; ++i) cout<<a[i]<<' '; cout<<endl;
		printf("%d\n", (b[j]%mod+mod)%mod);
	}
}

signed main()
{
	n=read(); p=read(); j=read();
	task::solve();
	
	return 0;
}
posted @ 2022-01-11 21:33  Administrator-09  阅读(0)  评论(0编辑  收藏  举报