大 河 的 序 列 大河的序列 大河的序列
题目链接:luogu P4144
题目
大河有一些袜子,但经常十分散乱的堆放着。
有一天龙儿忍不住了,于是将袜子放到了一个序列上(称作袜子序列)。
每个袜子都有一个dirtydirty值,定义袜子序列的dirtydirty值为 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 + + C++ C++中是 & & &), b i t o r bitor bitor表示按位或( C + + C++ C++中是 | | |)。
简而言之,就是找一段连续子序列,使得所有数字的按位与加上按位或最大。
如果这个袜子序列的dirtydirty值达到了某个阈值,那么龙儿会讨厌大河的。
大河当然不希望这样了,于是她想知道这个袜子序列的dirtydirty值是多少。
输入
第一行三个整数
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
样例输入
10 1 10000000
7 9 9 4 0 0 8 8 4 7
样例输出
251
数据范围
1
≤
n
,
p
≤
1
0
5
1≤n,p≤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
和
测
试
点
2
的
数
据
,
保
证
1
≤
n
≤
100
对于测试点1和测试点2的数据,保证 1 \le n \le 100
对于测试点1和测试点2的数据,保证1≤n≤100
思路
这道题看起来很难,但是我们用了一个贪心之后,就没有那么难了。
(虽然对我来说还是很难)
那么怎么用贪心呢?
我们可以通过观察和尝试发现,把两个数的和与或加起来,它的值一定会小于等于这两个数的其中一个。那么,既然加多值会更小,那不如只拿一个。
所以我们找到序列中最大的数,把它乘二(因为没有进行与和或,所以与和或都是数本身)。再进行快速幂就可以了。
代码
#include<cstdio>
#define ll long long
#define max(x,y) (x)>(y)?(x):(y);
using namespace std;
ll n,b,p,maxn,x;
ll ksm(ll di,ll zhi)//快速幂
{
ll ans=1;
ans%=p;
while (zhi)
{
if (zhi&1)
{
ans=ans*di%p;
zhi--;
}
di=di*di%p;
zhi/=2;
}
return ans%p;
}
int main()
{
scanf("%lld%lld%lld",&n,&b,&p);//读入
for (ll i=1;i<=n;i++)
{
scanf("%lld",&x);//读入
maxn=max(maxn,x);//求出最大值
}
maxn*=2;//与和或相加,所以乘二
printf("%lld",ksm(maxn+233,b));//输出
return 0;
}