UPC-序列

42 篇文章 1 订阅
30 篇文章 8 订阅

世 上 没 有 绝 望 的 处 境
只 有 对 处 境 绝 望 的 人

题目介绍

题目描述

eobiyye给了你一个长度为n的序列ai,序列中每个元素的初始值为0。
接下来她会对这个序列进行m次操作,每次操作有4个参数l,r,s,e,表示将区间[l,r]加上一个首项为s,末项为e的等差数列。
若一次操作中l=1,r=5,s=2,e=10,则对序列中第1~5个数分别加上2,4,6,8,10。
现在Geobiyye要求你求出m次操作后序列中的每个数的值。

输入

第一行2个整数n,m,表示序列长度和操作数。
接下来m行,每行4个整数l,r,s,e,含义见题目描述。
数据保证等差数列中的每一项都是整数。

输出

由于输出数据过大,Geobiyye只想要知道最终序列每一项的异或和,即a1⊕a2⊕a3⊕……⊕an。其中⊕表示二进制下的异或操作,在c++中为^)

测试样例

Sample Input

5 2
1 5 2 10
2 4 1 1

Sample Output

3

提示

样例解释:
第一次操作加的数列:2 4 6 8 10
第二次操作加的数列:0 1 1 1 0
所有操作结束后序列每个元素值为:2 5 7 9 10。
输出异或和,就是3。


【数据范围】
对于30%的数据:n,m≤1000 。
对于50%的数据:n,m≤100000。
对于另外20%的数据:s=e。
对于100%的数据:n,m≤500000,1≤l<r≤n。
数据保证输入数据以及在任何时候序列中的数在[0,9×1018]范围内。

本题输入文件较大,Geobiyye给了你一份快速读入的模板。

template <typename T> void read(T &x){
int f=1;x=0;char c=getchar();
for (;!isdigit(c);c=getchar()) if (c=='-') f=-f;
for (; isdigit(c);c=getchar()) x=x*10+c-'0';
x*=f;
}

你可以使用函数read(x)读入一个int或long long类型的整数。


以下为示范程序:

#include<bits/stdc++.h>
using namespace std;
template <typename T> void read(T &x){
int f=1;x=0;char c=getchar();
for (;!isdigit(c);c=getchar()) if (c=='-') f=-f;
for (; isdigit(c);c=getchar()) x=x*10+c-'0';
x*=f;
}
int n;
long long m;
int main(){
read(n);//读入int类型变量n
read(m);//读入long long类型变量m
return 0;
}

保证不会出现小数的情况

题目分析

题目大意

选择任意段,起始点为首,终点为尾,添加一个等差数列,这个数列已经告诉你a1和an,你也知道l 和 r,所以你也知道数列的长度。经过多次的叠加之后,问你这个数列所有数的异或和是多少。

思路分析

这题思路就是一个差分数组的思想,只不过这个地方需要用到二维的差分,需要对你的等差数列进行差分。当我们进行一步差分的时候,我们可以得到公差,和首相。然后对这个数列进行差分,就可以用首和尾来表示整个数组。说起来有些抽象,请看下图:
在这里插入图片描述
之后就和差分数组的做法没什么区别了!

代码

#include<algorithm>
#include<iostream>
#include<string.h>
#include <iomanip>
#include<stdio.h>
#include<utility>
#include<vector>
#include<string>
#include<math.h>
#include<cmath>
#include<queue>
#include<stack>
#include<deque>
#include<map>
#include<set>
#pragma warning(disable:4244)
#define PI 3.141592653589793
#pragma GCC optimize(2)
#define accelerate cin.tie(NULL);cout.tie(NULL);ios::sync_with_stdio(false);
#define EPS 1.0e-8
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const ll ll_inf = 9223372036854775807;
const int int_inf = 2147483647;
const short short_inf = 32767;
const char char_inf = 127;
ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }
inline ll read() {
	ll c = getchar(), Nig = 1, x = 0;
	while (!isdigit(c) && c != '-')c = getchar();
	if (c == '-')Nig = -1, c = getchar();
	while (isdigit(c))x = ((x << 1) + (x << 3)) + (c ^ '0'), c = getchar();
	return Nig * x;
}
inline void out(ll a) {
	if (a < 0)putchar('-'), a = -a;
	if (a >= 10)out(a / 10);
	putchar(a % 10 + '0');
}
ll phi(ll n)
{
	ll ans = n, mark = n;
	for (ll i = 2; i * i <= mark; i++)
		if (n % i == 0) { ans = ans * (i - 1) / i; while (n % i == 0)n /= i; }
	if (n > 1)ans = ans * (n - 1) / n; return ans;
}
ll qpow(ll x, ll n, ll mod) {
	ll res = 1;
	while (n > 0) {
		if (n & 1)res = (res * x) % mod;
		x = (x * x) % mod;
		n >>= 1;
	}
	return res;
}
ll mat_mod;
struct Mat {
	ll m[10][10];
};
Mat Mul(Mat A, Mat B, ll mat_size) {
	Mat res;
	memset(res.m, 0, sizeof(res.m));
	for (int i = 0; i < mat_size; i++)for (int j = 0; j < mat_size; j++)for (int k = 0; k < mat_size; k++)
		res.m[i][j] = (res.m[i][j] + (A.m[i][k] * B.m[k][j]) % mat_mod) % mat_mod;
	return res;
}
Mat mat_qpow(Mat data, ll power, ll mat_size) {
	Mat res;
	memset(res.m, 0, sizeof(res.m));
	for (int i = 0; i < mat_size; i++)res.m[i][i] = 1;
	while (power) {
		if (power & 1)res = Mul(res, data, mat_size);
		data = Mul(data, data, mat_size), power >>= 1;
	}
	return res;
}
#define Floyd for(int k = 1; k <= n; k++)for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)
#define read read()
ll save[1000005];
void solve()
{
	ll l = read, r = read, a = read, end = read, d, len;
	len = r - l;
	d = (end - a) / len;
	save[l] += a;
	save[l + 1] += (d - a);
	save[r + 1] -= a + (len + 1) * d;
	save[r + 2] += a + len * d;
}
int main()
{
	ll n = read;
	ll T = read;
	while (T--)solve();
	for (ll i = 2; i <= n; i++)
		save[i] += save[i - 1];
	for (ll i = 2; i <= n; i++)
		save[i] += save[i - 1];
	ll ans = 0;
	for (ll i = 1; i <= n; i++)ans ^= save[i];
	cout << ans << endl;
}

By-轮月

1)该程序的功能是将从IN单元读入的数据进行加法运算,然后将结果输出到OUT单元进行显示。具体的执行过程如下: - 第一条指令将从IN单元读入的数据存储到R0; - 第二条指令将R0的值与自身相加,结果仍然存储在R0; - 第三条指令将R0的值输出到OUT单元进行显示; - 第四条指令跳转回程序的起始地址,即第一条指令的位置,开始下一次循环。 假设输入值分别是00110011B和11001100B,则经过一次循环后,R0的值为$00110011_2+00110011_2=01100110_2$,即十六进制表示为$36_{16}$,则OUT单元会显示$36_{16}$,接着程序会回到起始地址,再次读入输入值进行加法运算和输出。 2)微程序流程图如下: ![微程序流程图](https://img-blog.csdnimg.cn/20220701110544631.png) 在一个循环过程,微指令的执行序列如下: - 第一条指令(取指令):从存储器读取指令并存储到IR寄存器; - 第二条指令(R0 -> A, uPC=09):将R0的值传输到A寄存器,并将uPC设置为09; - 第三条指令(R0 -> B, uPC=0A):将R0的值传输到B寄存器,并将uPC设置为0A; - 第四条指令(A+B -> R0, uPC=0):将A寄存器和B寄存器的值相加,结果存储到R0,并将uPC设置为0; - 第五条指令(IN -> R0, uPC=0):从IN单元读入数据存储到R0,并将uPC设置为0; - 第六条指令(R0 -> OUT, uPC=0):将R0的值输出到OUT单元进行显示,并将uPC设置为0; - 第七条指令(MEM -> PC, uPC=0):从存储器读取下一条指令的地址,并存储到PC寄存器,并将uPC设置为0。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Round moon

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值