洛谷P4144 大河的序列(极简版)

题目(自述):有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;
}

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值