l洛谷 (水题)P4144 大河的序列

题目

Solution:

  这题前面都是废话,关键的一句就是本题求的是序列中连续一段的相与值(&)+相或值(|)最大,然后对这个值进行快速幂取模。考虑到两个数相与最大能得到的就是这两个数中的最大值,那么不妨只取出序列中的最大数,然后逐个加数进行操作,容易想到当相或时要使最大数的值变大必然至少要使原数值的二进制中的一个0变为1,而再去相与时必然会使原数减小最少是相或增加的值(例如:假设最大值是101,此时加入数10,则相或变为111,但是相与会变为10,减少的比增加的要多),于是贪心的思想我们直接选取序列中的最大值,而题目中的连续一段可以是一个数,那么,连续一段的相与值+相或值最大就是 最大数*2,然后对这个数快速幂取模就ok了。(注意:题目中b可以为0,按理说输出是1,但是莫名其妙数据中要输出0)

代码:

 1 // luogu-judger-enable-o2
 2 #include<bits/stdc++.h>
 3 #define ll long long
 4 #define il inline
 5 using namespace std;
 6 ll  n,p,b,a[100005],num;
 7 il void gi(ll &c)
 8 {
 9     c=0;char x=getchar();bool f=0;
10     while((x<'0'||x>'9'))x=getchar();
11     while(x>='0'&&x<='9')c=c*10+x-48,x=getchar();
12 }
13 il ll fast(ll x,ll b)
14 {
15     ll a=1;
16     while(b){
17         if(b&1)a=a*x%p;
18         b>>=1;
19         x=x*x%p;
20     }
21     return a;
22 }
23 int main()
24 {
25     gi(n),gi(b),gi(p);
26     if(b==0){printf("0");return 0;}
27     for(int i=1;i<=n;i++)gi(a[i]),num=max(a[i],num);
28     num<<=1;
29     printf("%lld",fast(num+233,b));
30     return 0;
31 }
原文地址:https://www.cnblogs.com/five20/p/8366711.html