COCI2017-2018#3 Dojave || 洛谷P4443
The biggest event of the year ended tragically for Croatian teams. The most influential theoretician of CERC of all time, the founder of the popular page CERC Tips, and in his free time an outstanding bass player, in his most recent performance failed to get his team to the finals.
In order to get over his existential troubles, our subject is spending time playing games of chance. He is especially interested in the following game:
You are given a positive integer M. Our protagonist sees in front of him a permutation of an array of numbers 0, 1, 2, ..., 2^M2M - 1.
The computer chooses a nonempty contiguous subsequence of the given permutation, which it then lights up over a capital city of one of the countries in Southeastern Europe.
Our confidant, after fighting off tears caused by memories of old times, must choose two distinct elements of the permutation and swap their places. Our man of the hour wins if and only if the bitwise XOR of the numbers in the lit up subsequence after the substitution is precisely 2^M2M - 1.
Our hero wants to know the number of contiguous subsequences the computer can light up so that he can win.
Help our hero overcome his (id)entity crisis so our favourite page can be fully active again.
输入输出格式
输入格式:
The first line of input contains the integer M (1 ≤ M ≤ 20),
The following line contains 2^M2M space-separated numbers that make up a permutation of the array 0, 1, 2, ..., 2^M2M - 1.
输出格式:
You must output the total number of contiguous subsequences that a computer can light up so our hero can win.
输入输出样例
说明
In test cases worth 50% of total points, it will hold 1 ≤ M ≤ 14.
Clarification of the test cases:
In the first test case, if the computer chooses the subsequence [1 2 3], our hero can replace the numbers 0 and 3. In this case, he can actually win for every chosen contiguous subsequence, except the entire array.
In the second test case, if the computer chooses the entire array [3 7 0 4 6 1 5 2] as the lit up subsequence, our hero can’t change the XOR of the subsequence (which is 0), no matter which two elements are swapped.
https://www.luogu.org/problemnew/show/P4443
题目大意 ::
给定一个正整数M,和0到2M-1共2M个数的排列,计算机先选择一段连续的子串,你必须选两个不同的元素出来,交换它们的位置,使得计算机选出来的子串在交换后的元素的异或值为2M-1,如果可以,你将获胜。现在请你统计有多少种不同的选法,你可以获胜。
就是叫你求出所有满足条件的区间的个数。。。
官方标程是 线段树 + !@#¥%…… 我看不懂......(orz洛谷大佬写的线段树)......
线段树 :: //这个真的看不懂QAQ......
//for test!
#include <bits/stdc++.h>
using namespace std;
#define ms(s, n) memset(s, n, sizeof(s))
#define FOR(i, a, b) for (int i = (a); i < (b); i++)
#define FORd(i, a, b) for (int i = (a) - 1; i >= (b); i--)
#define FORall(it, a) for (__typeof((a).begin()) it = (a).begin(); it != (a).end(); it++)
#define sz(a) int((a).size())
#define present(t, x) (t.find(x) != t.end())
#define all(a) (a).begin(), (a).end()
#define uni(a) (a).erase(unique(all(a)), (a).end())
#define pb push_back
#define pf push_front
#define mp make_pair
#define fi first
#define se second
#define prec(n) fixed<<setprecision(n)
#define bit(n, i) (((n) >> (i)) & 1)
#define bitcount(n) __builtin_popcountll(n)
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef pair<int, int> pi;
typedef vector<int> vi;
typedef vector<pi> vii;
;
;
const int INF = (int) 1e9;
const ll LINF = (ll) 1e18;
);
;
inline ll gcd(ll a, ll b) {ll r; while (b) {r = a % b; a = b; b = r;} return a;}
inline ll lcm(ll a, ll b) {return a / gcd(a, b) * b;}
inline ll fpow(ll n, ll k, ; ) {) r = r * n % p; n = n * n % p;} return r;}
template< : ;}
template< : ;}
inline ll isqrt(ll k) {ll r = sqrt(k) + ; while (r * r > k) r--; return r;}
inline ll icbrt(ll k) {ll r = cbrt(k) + ; while (r * r * r > k) r--; return r;}
inline void addmod(int& a, int val, int p = MOD) {if ((a = (a + val)) >= p) a -= p;}
inline ) a += p;}
inline int mult(int a, int b, int p = MOD) {return (ll) a * b % p;}
inline , p);}
inline : x > +EPS;}
inline int sign(ld x, ld y) {return sign(x - y);}
#define db(x) cerr << #x << " = " << (x) << " ";
#define endln cerr << "\n";
<< ;
int n;
int a[maxn];
int f[maxn];
];
int mn[maxn];
int mx[maxn];
][maxn << ];
void updmn(int st[], int p, int val) {
; ) p >>= , st[p] = min(st[p << ], st[p << | ]);
}
int querymn(int st[], int l, int r) {
int res = INF;
; l < r; l >>= , r >>= ) {
) chkmin(res, st[l++]);
) chkmin(res, st[--r]);
}
return res;
}
void updmx(int st[], int p, int val) {
; ) p >>= , st[p] = max(st[p << ], st[p << | ]);
}
int querymx(int st[], int l, int r) {
int res = -INF;
; l < r; l >>= , r >>= ) {
) chkmax(res, st[l++]);
) chkmax(res, st[--r]);
}
return res;
}
void solve() {
cin >> n; n = << n;
FOR(i, , n) mn[i] = INF, mx[i] = -INF;
FOR(i, , n) {
cin >> a[i];
chkmin(a[i], a[i] ^ n - );
chkmin(mn[a[i]], i);
chkmax(mx[a[i]], i);
}
) {
cout << << "\n";
return;
}
FOR(i, , n) {
updmn(st[], i, mn[a[i]]);
updmx(st[], i, mx[a[i]]);
}
;
FOR(i, , n) {
int k = a[i];
if (mx[k] == i) {
f[i] = -;
], mn[k], mx[k]);
if (j >= mn[k]) {
f[i] = j;
}
else {
f[i] = f[mx[a[j]]];
}
&& querymx(st[], f[i], i) <= i) {
;
& ;
dp[i][par] = ;
if (f[i]) {
dp[i][par] += dp[f[i] - ][];
dp[i][par ^ ] += dp[f[i] - ][];
}
res -= dp[i][];
}
}
}
res += () / ;
cout << res << "\n";
}
int main(int argc, char* argv[]) {
ios_base::sync_with_stdio(), cin.tie();
) {
assert(freopen(argv[], "r", stdin));
}
) {
assert(freopen(argv[], "wb", stdout));
}
solve();
;
}//标程....
但是我只会写写被数据卡到飞起的hash......怎么办?一个hash不行就2个嘛......
hash : : //代码极丑.......毕竟是蒟蒻.......体谅下
//hash 有毒, 双hash才可过 ;
#include <cstdio>
#include <map>
using namespace std;
typedef long long ll;
<< ;
map<pair<ll, ll>, ];
; return c = 1ll * c * 15315ll % 0x7fffffff; }
], pos[N + ], f1[N + ], f2[N + ], r1[N + ], r2[N + ];
int main() {
scanf( << n; ll ans = 1ll * c * (c + ) / 2ll;
; i <= c; i ++) scanf("%d", a + i), pos[a[i]] = i;
; i <= c / ; i ++) r1[pos[i]] = r1[pos[i ^ (c-)]] = rand(), r2[pos[i]] = r2[pos[i ^ (c-)]] = rand();
; i <= c; i ++) f1[i] = f1[i-] ^ r1[i], f2[i] = f2[i-] ^ r2[i];
; i <= c; i ++) ans -= p[i % ][make_pair(f1[i], f2[i])], p[i % ][make_pair(f1[i], f2[i])] ++;
printf(n == ? " : "%lld\n", ans);
}
证明如下 ::
设 k = (1 << M) - 1; pos[] 表示值为 x 的数的位置;
首先考虑区间长度为奇数的时候, 设区间的xor值为 A, 则将其中某个数换走后的xor值为 A ^a[i], 那么要使区间 xor值 为 k, 则需要换一个 a[j] = k ^ A ^a[i] (这不是废话么......), 设 g = k ^ A(这是个定值)
假设该区间不合法, 则有 pos[g ^ a[1]] ∈ [l, r], pos[g ^ a[2]] ∈ [l, r]......,因为 a[i] != a[j], 所以g ^ a[i] != g ^a[j](又是废话),
所以g ^ a[1] ^ g ^ a[2] ^ .... g ^ a[n] = a[1] ^ a[2] ^ ...^a[n], 所以g ^ a[1] ^ a[2] ^ ... ^a[n] == a[1] ^ a[2] ^ ... ^ a[n], 所以当前情况 g = 0。。。又 g = k ^ A,所以 k == A (与假设矛盾)。 所以当区间长度为奇数时一定是
合法区间。
好, 现在开始考虑区间长度为偶数时 先讨论 区间长度 / 2 为奇数时
同样,如果为不合法区间 (假设) ,则有 a[ i ] ^ g = a[ j ], pos[ a[ i ] ] ∈ [l, r], pos[ a[ j ] ] ∈ [l, r]; 又因为 g = a[ i ] ^ a[ j ]; 所以最后区间的 xor 值一定为 g (自己想一想)。
所以 A = a[i] ^ a[j]。 g = K ^ A = a[i] ^a[j]; k ^ a[i] ^ a[j] = a[i] ^a[j]。(好像在哪里见过。。。。)
现在讨论区间长度为偶数且区间长度 / 2 为偶数的情况
同上,区间的 xor 值 A 为 0(不想解释了,反正上面看懂了也很简单), 则有 g = K(g = k ^ A), 所以 a[ i ] ^ a[ j ] = k (对于任意a[i]都只有一个a[j]与之异或等于K,不想证明了), 所以到这里我们就把所有不合法区间的条件求出了。
总结下,现在我们知道了区间的总数为 (k + 2) * (k + 1) / 2,区间长度为4的倍数且其中的数都是配♂对的数的区间不合法,减去,双hash乱搞ok(一个hash让我Wa到怀疑人生);
证明完毕。。。(我语文很差,可能有的地方表达有误。谁看懂标程的可以说下否?)

COCI2017-2018#3 Dojave || 洛谷P4443的更多相关文章
- 2018.07.01洛谷P2617 Dynamic Rankings(带修主席树)
P2617 Dynamic Rankings 题目描述 给定一个含有n个数的序列a[1],a[2],a[3]--a[n],程序必须回答这样的询问:对于给定的i,j,k,在a[i],a[i+1],a[i ...
- 2018.07.17 洛谷P1368 工艺(最小表示法)
传送门 好的一道最小表示法的裸板,感觉跑起来贼快(写博客时评测速度洛谷第二),这里简单讲讲最小表示法的实现. 首先我们将数组复制一遍接到原数组队尾,然后维护左右指针分别表示两个即将进行比较的字符串的头 ...
- 2018.12.30 洛谷P4238 【模板】多项式求逆
传送门 多项式求逆模板题. 简单讲讲? 多项式求逆 定义: 对于一个多项式A(x)A(x)A(x),如果存在一个多项式B(x)B(x)B(x),满足B(x)B(x)B(x)的次数小于等于A(x)A(x ...
- 2018.11.09 洛谷P1110 [ZJOI2007]报表统计(multiset)
传送门 sb题. 直接用两个multisetmultisetmultiset维护相邻两个数的差值和所有数的前驱后继. 插入一个数的时候更新一下就行了. 代码: #include<bits/std ...
- 2018.11.06 洛谷P1099 树网的核(最短路+枚举)
传送门 之前看李煜东的书一直感觉是道神题. 然后发现这题数据范围只有300?300?300? 直接上floydfloydfloyd然后暴力就完了啊. 代码: #include<bits/stdc ...
- 2018.11.06 洛谷P1941 飞扬的小鸟(背包)
传送门 上升看成完全背包. 下降看成01背包. 注意边界转移就行了. 代码: #include<bits/stdc++.h> using namespace std; inline int ...
- 2018.11.04 洛谷P2679 子串(线性dp)
传送门 为什么前几年的noipnoipnoip总是出这种送分题啊? 这个直接线性dpdpdp不就完了吗? f[i][j][k][0/1]f[i][j][k][0/1]f[i][j][k][0/1]表示 ...
- 2018.11.04 洛谷P1081 开车旅行(倍增)
传送门 思路简单码量超凡? 感觉看完题大家应该都知道是倍增sbsbsb题了吧. 首先预处理出从每个点出发如果是AAA走到哪个点,如果是BBB走到哪个点. 然后利用刚刚预处理出的信息再预处理从每个点出发 ...
- 2018.11.02 洛谷P2661 信息传递(拓扑排序+搜索)
传送门 按照题意模拟就行了. 先拓扑排序去掉不在环上面的点. 剩下的都是简单环了. 于是都dfsdfsdfs一遍求出最短的环就行. 代码: #include<bits/stdc++.h> ...
随机推荐
- 【总结整理】如何判断伪需求(摘自pmcafe)
1.客户不会直接提需求,都是给解决方案,所以得到用户的反馈之后,先反推一下是很必要的,为什么客户会有这样的方案 总结:方案不合适 例如:客户只会说我要快马,反推一下,其实客户是想要更快,这样的话,解决 ...
- C++——多线程
1.多进程和多线程:进程是一个总任务,一个进程可能包含多个线程. 2.并行和并发: 并发的关键是你有处理多个任务的能力,不一定要同时. 并行的关键是你有同时处理多个任务的能力. 3.共享数据的管理和线 ...
- 507. Perfect Number 因数求和
[抄题]: We define the Perfect Number is a positive integer that is equal to the sum of all its positiv ...
- How to install Freemind 1.0.1 to Ubuntu 14
安装了Freemind0.9后发现不能打开windows的1.0.1保存的*.mm文件,便对版本开始升级. 1. 从http://freemind.sourceforge.net/wiki/index ...
- 618F Double Knapsack
传送门 题目大意 分析 代码 #include<iostream> #include<cstdio> #include<cstring> #include<s ...
- oracle 中 创建序列sequence
drop sequence SEQ_YCXWP_CGD; create sequence SEQ_YCXWP_CGD increment start nomaxvalue;
- 国外物联网平台(5):Exosite Murano
国外物联网平台(5)——Exosite Murano 马智 定位 Murano是一个基于云的IoT软件平台,提供安全.可扩展的基础设施,支持端到端的生态系统,帮助客户安全.可扩展地开发.部署和管理应用 ...
- HackSix 为ViewGroup的子视图添加悦目的动画效果
1.默认情况下他,添加到viewGrop的子视图是直接显示出来的.有一个比较简单的方法可以为这个过程增加动画效果. 2.知识点: 给子视图添加动画效果就用:LayoutAnimationCon ...
- web利用table表格生成excel格式问题
当我们把web页面上的table导成excel形式时,有时候我们的数据需要以特定的格式呈现出来,这时候我们就需要给指定的单元格添加一些样式规格信息. 文本:vnd.ms-excel.numberfor ...
- .net core 图片合并,图片水印,等比例缩小,SixLabors.ImageSharp
需要引用 SixLabors.ImageSharp 和SixLabors.ImageSharp.Drawing 引用方法 NuGet包管理 添加程序包来源 https://www.myget.org/ ...