题解 异或矩阵
首先可以分析转移路径做到 \(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;
}