大河的序列
题目背景
“唯有龙虎相伴 最是脉脉深情”
题目来源:KingSann
题目描述
大河有一些袜子,但经常十分散乱的堆放着。
有一天龙儿忍不住了,于是将袜子放到了一个序列上(称作袜子序列)。
每个袜子都有一个
d
i
r
t
y
dirty
dirty值,定义袜子序列的
d
i
r
t
y
dirty
dirty值为
max
(
(
d
i
r
t
y
l
b
i
t
a
n
d
d
i
r
t
y
l
+
1
b
i
t
a
n
d
⋯
b
i
t
a
n
d
d
i
r
t
y
r
)
+
(
d
i
r
t
y
l
b
i
t
o
r
d
i
r
t
y
l
+
1
b
i
t
o
r
⋯
b
i
t
o
r
d
i
r
t
y
r
)
)
\max \left( (dirty_{l} \ bitand \ dirty_{l+1} \ bitand \ \cdots \ bitand \ dirty_{r}) + (dirty_{l} \ bitor \ dirty_{l+1} \ bitor \ \cdots \ bitor \ dirty_{r}) \right)
max((dirtyl bitand dirtyl+1 bitand ⋯ bitand dirtyr)+(dirtyl bitor dirtyl+1 bitor ⋯ bitor dirtyr)) ,其中
d
i
r
t
y
i
dirty_{i}
dirtyi 表示 第
i
i
i 只袜子 的
d
i
r
t
y
dirty
dirty 值,
b
i
t
a
n
d
bitand
bitand表示按位与(C++中是&
),
b
i
t
o
r
bitor
bitor表示按位或(C++中是|
)。
简而言之,就是找一段连续子序列,使得所有数字的按位与加上按位或最大。
如果这个袜子序列的 d i r t y dirty dirty值达到了某个阈值,那么龙儿会讨厌大河的。
大河当然不希望这样了,于是她想知道这个袜子序列的 d i r t y dirty dirty值是多少。
输入格式
第一行三个整数 n , b , p n,b,p n,b,p ,分别表示数列长度和输出相关的东西
第二行有 n n n 个整数,表示这个数列的初始数值
输出格式
设答案为 x x x ,你需要输出 ( x + 233 ) b mod p (x+233)^{b} \,\, \text{mod} \,\,p (x+233)bmodp。
样例 #1
样例输入 #1
10 1 10000000
7 9 9 4 0 0 8 8 4 7
样例输出 #1
251
提示
1 ≤ n , p ≤ 1 0 5 1 \le n, p \le 10^{5} 1≤n,p≤105。
0 ≤ b , d i t r y i ≤ 1 0 7 0 \le b, ditry_{i} \le 10^{7} 0≤b,ditryi≤107。
对于测试点 1 1 1 和测试点 2 2 2 的数据,保证 1 ≤ n ≤ 100 1 \le n \le 100 1≤n≤100。
思路
对于题目的式子,我们定义:
s 1 = { d i and d i + 1 and d i + 1 , ⋯ d j − 1 and d j } s_1=\{d_i\ \text{and}\ d_{i+1}\ \text{and}\ d_{i+1},\cdots d_{j-1} \ \text{and}\ d_{j}\} s1={di and di+1 and di+1,⋯dj−1 and dj}
s 2 = { d i or d i + 1 or d i + 1 , ⋯ d j − 1 or d j } s_2=\{d_i\ \text{or}\ d_{i+1}\ \text{or}\ d_{i+1},\cdots d_{j-1} \ \text{or}\ d_{j}\} s2={di or di+1 or di+1,⋯dj−1 or dj}
求一个子序列,使得 s 1 + s 2 s_1+s_2 s1+s2 尽可能大。
此时假设现在存在一个子序列 s k s_k sk,那么现在要加入一个数 c c c,那么我们按位来看情况如何:
对于其中的某一位, c c c 在这一位一定存在两种情况: 0 0 0 或者位 1 1 1,我们也知道什么时候能同时满足二者最优,那么肯定是:尽可能每位要 1 1 1。
而这样的一个 1 1 1 对于高位的贡献显然是大于低位的,所以我们要找的序列都要尽可能大,而任何一个 c c c,如果比原来的序列中所有数都小,那么它是无需加入的(也就是说,贡献为负)。
那么我们从任何一个数开始,把所有比他大的数加进来,那他对这个序列的贡献就是负了,那么我们就可以把它移除…依次类推,只留下了最大的数。
那么我们计算的时候,由于没有别的数,就等于将它计算了两边,此时答案就是 2 × m a x 2\times max 2×max。
- 细节1:本题规定 0 0 = 0 0^0=0 00=0。
代码
//结论 两倍
#include<iostream>
#include<algorithm>
#include<cstring>
#define int long long
using namespace std;
const int N = 1e5+10;
int w[N];
int n,b,p;
int maxv;
int qmi(int a,int b,int p){
int res=1;
while(b){
if(b&1)res=res*a%p;
a=a*a%p;
b>>=1;
}
return res;
}
signed main(){
cin>>n>>b>>p;
for(int i=1;i<=n;i++){
cin>>w[i];
maxv=max(w[i],maxv);
}
maxv*=2;
if(p==1&&b==0){
cout<<0;
}else{
cout<<qmi(maxv+233,b,p)<<endl;
}
return 0;
}