题目(自述):有n只袜子,每只袜子有一个脏值xi,对编号从i到j的连续袜子有一个判断标准t
t=xi&xi+1&xi+2......&xj+xi|xxi+1|xi+2......|xj
问对所有的袜子,求一个i和j使其t最大;
输入格式
第一行三个整数 n,b,p
第二行有 n 个整数,表示这些袜子的初始数值
输出格式
设答案为 x ,你需要输出 (x+233)^b mod p
数据
1≤n,p≤10^5
0≤b,xi≤10^7
任务一:求x
前提1:
设值a,b(取1或0)
b=1:a&b=a不变 a|b=1可能变大或者不变
b=0:a&b=0可能变小或者不变 a|b=a不变
扩展到多位也是一样
前提二:
设值a,b,a>b(任意自然数的二进制)
序列中只有a时:t=a+a
序列中加入b:t=a&b+a|b,因为a>b,对于b而言,若位数与a相同(例如1100与1010或者1100与0110),b中0比较靠近高位,而1靠近低位,而且因为是将b加入a的序列,所以是由b的值决定t;
a&b中,b偏向于将a的较高位的1变成0,(见前提1),而低位的0不变1,这让a变小的更多
a|b中,b偏向于将a的较低位的0变成1,(见前提1),而高位的0不变1,这让a变大的更少
因此,若满足a>b,那么t(a)>t(a,b)
结论:
根据前提一和二,我们假设取最大值xi到序列,这时不管添加多少元素到序列,最后的t都不会大于只有xi时的t,也就是2*xi
结果x=2*max(xi)
任务二:输出(x+233)^b mod p
难点:x和b的最大取值范围都是10^7,所以x^b可能超出能存储的数据范围;
解答前的例子:(很简单也很详细)x+233=7 ,b=7,p=4,也就是求(7^7)%4
假设这个数据很大以至于不能先算7^7,那么我们把他展开一点
(7^7)%4=(7*7^6)%4=[(4+3)*7^6 = 4*7^6 + 3*7^6]%4=3*7^6%4
再展开就是(3*7*7^5)%4=(3*(4*3)*7*5)%4同理=3*3*7^5%4=9*7^5%4=(8+1)*7^5%4=7^5%4
结论:对于x^b对p求余,我们先取一个x,每次乘一个x,对于乘法两边的值分别对p求余,然后再相乘,结果再对p求余作为一个新的值,再往里面乘x,直到把所有x相乘,因为每一步都会对p求余,所以不会有数值超过范围
最后再输出即可(记住在洛谷想要ac就一定要特判,内容如代码所示)
代码:
#include <iostream>
using namespace std;
int main()
{
int n, b, p;
long long maxN = 0, sum = 1, t = 0;
cin >> n >> b >> p;
//特判
if (b == 0) {
cout << 0;
return 0;
}
//求x
for (int i = 0; i < n; i++) {
cin >> t;
maxN = max(maxN, t);
}
//求输出内容
maxN = maxN * 2 + 233;
for (int i = 0; i < b; i++) {
sum = ((sum % p) * (maxN % p)) % p;;
}
//输出
cout << sum;
return 0;
}