首页 > 其他分享 >位位运算 方法记录

位位运算 方法记录

时间:2022-10-09 17:46:43浏览次数:81  
标签:__ 运算 子段 位位 记录 stu ans int128 小朋友



题解

我们首先来分析小朋友的三个指标:手里的数,特征值,分数。

手里的数:即我们输入的长度为\(n\)的序列;

特征值:从第一个小朋友到当前小朋友的 手上的数最大子段和

分数:当前小朋友前面的小朋友中 小朋友特征值和分数的和 的最大值(第一个小朋友的分数等于其特征值)。

这个问题可以拆分成两个子问题。

一、求每个小朋友对应的最大子段和

最大子段和模板题

最大子段和的核心思想

1.第一个数是一个有效子段。

2.如果 一个数加上上一个有效子段 的结果 大于 这个数,那么 这个数属于上一个有效子段。

3.如果 一个数加上上一个有效子段 的结果 小于 这个数,那么 这个数成为一个新的有效子段。

	for(int i=1;i<=n;i++)
	{
		scanf("%lld",&hand);//hand是输入的手里的数 
		if(i==1) tmp[i]=hand;//tmp[]记录子段 
		else tmp[i]=maxx(hand,tmp[i-1]+hand);//取hand是第3种情况,取tmp[i-1]+hand是第2种情况 
		sub=maxx(sub,tmp[i]);//sub是第i个小朋友对应的最大子段和(特征值) 
		stu[i].spl=sub;
	}

注意

sub=maxx(sub,tmp[i]);
stu[i].spl=sub;

不能写成

stu[i].spl=maxx(stu[i].spl,tmp[i]);

因为\(sub\)后续还会用到,所以需要持久地保存下来。

二、线性统计所有小朋友分数的最大值

第一个小朋友的分数就是其特征值。

第二个小朋友前面只有一个小朋友,所以第二个小朋友的分数就是第一个小朋友分数和特征值之和。

……

记录当前小朋友的分数为\(x\),那么下一个小朋友的分数就是 \(x\)、下一个小朋友与\(x\)的和 的最大值。、

stu[1].sco=stu[1].spl;
	x=stu[1].sco+stu[1].spl;
	ans=stu[1].sco;
	for(int i=2;i<=n;i++)
	{
		stu[i].sco=x;
		x=maxx(x,stu[i].spl+stu[i].sco);
		ans=maxx(ans,stu[i].sco);
	}

考虑到数据范围导致运算时会出现超过\(long long\)的值,所以可以使用__128来声明参与运算的变量,注意输入输出不能用__128。

AC代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const __int128 N=1000005;
const __int128 inf=2147483647;
ll n,p,hand;
__int128 x,ans;
struct student
{
	__int128 spl,sco;
}stu[N];
__int128 tmp[N];
__int128 maxx(__int128 a,__int128 b)
{
	return a>b?a:b;
}
__int128 sub=-inf;
ll final;
signed main()
{
	//freopen("number.in","r",stdin);
	//freopen("number.out","w",stdout);
	scanf("%lld%lld",&n,&p);
	for(int i=1;i<=n;i++)
	{
		scanf("%lld",&hand);//hand是输入的手里的数 
		if(i==1) tmp[i]=hand;//tmp[]记录子段 
		else tmp[i]=maxx(hand,tmp[i-1]+hand);//取hand是第3种情况,取tmp[i-1]+hand是第2种情况 
		sub=maxx(sub,tmp[i]);//sub是第i个小朋友对应的最大子段和(特征值) 
		stu[i].spl=sub;
	}
	stu[1].sco=stu[1].spl;
	x=stu[1].sco+stu[1].spl;
	ans=stu[1].sco;
	for(int i=2;i<=n;i++)
	{
		stu[i].sco=x;
		x=maxx(x,stu[i].spl+stu[i].sco);
		ans=maxx(ans,stu[i].sco);
	}
	if(ans>=0)
	{
		ans=ans%p;
		final=ans;
		printf("%lld",final);
	}
	else
	{
		ans=-ans;
		ans=ans%p;
		final=ans;
		printf("-%lld",final);
	}
	return 0;
}

标签:__,运算,子段,位位,记录,stu,ans,int128,小朋友
From: https://www.cnblogs.com/fish4174/p/16773010.html

相关文章

  • 【博学谷学习记录】超强总结,用心分享|MySql连接查询超详细总结
    一、概述在实际开发中,大部分情况下都不是在单表中进行数据操作,一般都是多张表进行联合查询。通常一个业务就会对应的有好几张表。MySql中的连接查询分为交叉连接,内连......
  • uniapp--微信小程序 问题记录
    自动适配问题rem适配为什么选择rema)机型太多,不同的机型屏幕大小不一样b)需求:一套设计稿的内容在不同的机型上呈现的效果一致,根据屏幕大小不同的变化,页面中的内......
  • let、const命令(学习阮一峰ES6记录)
    1.let命令ES6新增let命令,作用和var类似,用来声明变量,但是let只能在所在代码块(区域)中使用。例:1{2leta=2;3varb=3;4}5console.log(a)//aisn......
  • docker部署项目注意事项记录
    1.不同容器之前通信,如前端容器与后端容器,需要注意配置文件(如前端nginx的nginx.conf,后端的application.yml)里的ip地址要为宿主机的具体ip,如192.168.0.12,而不能为loca......
  • 记录Linux下启动docker中Mysql,并进入mysql。
    1.启动dockersystemctlstartdocker  2.查看docker容器启动信息,并找到mysql容器  3.使用进程名启动mysql:dockerstartmysql-test;也可以使用进程id启动:docker......
  • java---了解以下运算符
    了解即可1&2用于条件判断,&条件1和2都执行1&&2,条件1判断错误的情况下,条件2不执行&当运算符的化,例如4&7,两者上下对比都是1则为1,反之为0,结果就是二进制100也就是......
  • 快速幂,位运算,pow()函数
    位运算:位运算可以用来查找01二进制串中1或0的个数,同时也可以实现幂的计算,但是只能是以2为底的幂运算统计字符串中1的个数#include<bits/stdc++.h>usingnamespacestd;......
  • 状压dp刷题记录【持续更新】
    前言:许多算法的状态数并不支持其在多项式时间内运行完成。比如TSP问题这种大部分为NP-Hard的问题。在数据范围缩小的前提下(例如\(n\leq21\)),不妨将状态数压缩成二进制情......
  • 布尔类型、比较运算符
    布尔类型True表示真(是、肯定)False表示假(否、否定)变量名称=布尔类型字面量比较运算符代码案例#定义变量存储布尔类型的数据bool_1=Truebool_2......
  • 一篇文章介绍 符号运算的妙用
    以后把看到的觉得有用的符号运算记录下来。符号运算效率会更高一点,虽然甚微,但是还是有的。我记录的都是实用的,要是用上自己都看不懂,就有点搬石头砸自己的脚了。 ## 判断......