题解 异或矩阵

传送门

首先可以分析转移路径做到 \(O(k(n-k+1))=O(n^2-nk)\)

然后就不好优化了

  • 网格图上的转移路径还有一大性质是可以分段转移

由库默尔定理知若 \(k-1=2^t\),则仅有 \(\binom{k-1}{0},\binom{k-1}{k-1}\) 是有值的
那么分成 \(\log\) 段转移即可
复杂度 \(O(n\log n)\)

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

uint n, k, x;

// namespace table{
// 	// int c[3000][3000];
// 	int fac[N], inv[N];
// 	void solve() {
// 		// c[0][0]=1;
// 		// for (int i=1; c[i][0]=1,i<=2000; ++i) for (int j=1; j<=i; ++j) c[i][j]=c[i-1][j]^c[i-1][j-1];
// 		fac[0]=fac[1]=1;
// 		// for (int i=0; i<=1000; ++i) {
// 		// 	for (int j=0; j<=i; ++j) cout<<setw(3)<<c[i][j]<<' '; cout<<endl;
// 		// }
// 		for (int i=0; i<=100; ++i) {
// 			for (int j=0; j<=i; ++j) cout<<setw(3)<<(c[i][j]&1)<<' '; cout<<endl;
// 			// int cnt=0;
// 			// for (int j=0; j<=i; ++j) if (c[i][j]&1) ++cnt;
// 			// cout<<i<<": "<<cnt<<endl;
// 		}
// 	}
// }

namespace task1{
	uint a[N], ans;
	inline uint C(int n, int k) {return (n&k)==k;}
	void solve() {
		a[1]=x;
		for (uint i=2; i<=n; ++i) a[i]=1145141*a[i-1]+1919*i+810;
		// for (int i=1; i<=n; ++i) cout<<a[i]<<' '; cout<<endl;
		for (uint i=1; i<=n-k+1; ++i) {
			uint tem=0;
			for (uint j=i,end=min(i+k,n+1); j<end; ++j) if (((k-1)&(j-i))==(j-i)) tem^=a[j];
			// cout<<tem<<' ';
			ans+=i*(tem^i);
		} //cout<<endl;
		cout<<ans<<endl;
	}
}

namespace task2{
	uint a[N], ans;
	uint sta[N], top;
	inline uint C(uint n, uint k) {return (n&k)==k;}
	void solve() {
		a[1]=x;
		for (uint i=2; i<=n; ++i) a[i]=1145141*a[i-1]+1919*i+810;
		for (uint i=0; i<k; ++i) if (C(k-1, i)) sta[++top]=i;
		for (uint i=1; i<=n-k+1; ++i) {
			uint tem=0;
			for (uint j=1; j<=top; ++j)
				if (i+sta[j]<=n) tem^=a[i+sta[j]];
				else break;
			ans+=i*(tem^i);
		}
		cout<<ans<<endl;
	}
}

signed main()
{
	freopen("matrix.in", "r", stdin);
	freopen("matrix.out", "w", stdout);

	cin>>n>>k>>x;
	// task1::solve();
	task2::solve();

	return 0;
}
posted @ 2022-03-25 15:13  Administrator-09  阅读(6)  评论(0编辑  收藏  举报