201905/16 膜你赛 日程表

题目:
【问题描述】
放暑假了,小 C 准备了一个日程表来安排他的暑假生活.
一共有 n 件事情,编号为 1; 2; :::; n,第 i 件事情的难度为 i. 小 C 将整个暑假划分为
m 个时刻,并设定了三个正整数 a; b; c. 然后,小 C 定义了一个数列 fxig,满足:
x0 = 0; xi = (axi−1 + b) mod 2nc (1 ≤ i ≤ m)
即从 x1 开始,数列的每一项等于上一项的 a 倍加上 b 以后除以 2nc 的余数.
在暑假刚开始时,小 C 的日程表是空的. 第 i 个时刻前,小 C 会根据 xi 的值决定日
程表的变化:
·若 xi < nc,则将编号为 ⌊ xci ⌋ + 1 的事件加入日程表,若日程表已有该事件则忽略;
·若 xi ≥ nc,则将编号为 ⌊ xci ⌋ − n + 1 的事件从日程表删除,若日程表没有该事件则
忽略;
第 i 个时刻(1 ≤ i ≤ m),小 C 所做的事情就是该时刻日程表中的所有事件.
对于每个时刻,小 C 定义该时刻的工作量为该时刻做了几件事情,该时刻的疲劳度为
该时刻做的所有事情的难度之和. 整个暑假小 C 的工作量为所有时刻的工作量之和,疲劳
度为所有时刻的疲劳度之和.
请根据 n; m; a; b; c 计算小 C 这个暑假的工作量和疲劳度.
【输入格式】
输入文件名为 schedule.in
输入一行,五个由空格分隔的正整数 n; m; a; b; c.
【输出格式】
输出文件名为 schedule.out
一行两个由空格分隔的整数,第一个数为小 C 这个暑假的工作量,第二个数为小 C 这
个暑假的疲劳度.
由于答案可能很大,请输出答案除以 1000000007 的余数.
【样例输入 13 6 4 1 5
【样例输出 18 13
思路:

考试的时候一直在想怎么统计答案……感觉是动态前缀和,就写了个bst骗了80分。
发现每一次答案和上一次相关,所以用bool数组表示每个数在不在就可以,统计答案时可以利用上一次的答案加减。

代码:
#include<bits/stdc++.h>
using namespace std;

#define maxn 50000000
#define ll long long
#define read(x) scanf("%lld",&x)
#define md 1000000007
#define lowbit(x) x&-x;

ll n,m,a,b,c;
bool f[maxn+5];

int main() {
	read(n),read(m),read(a),read(b),read(c);
	
	ll x=0,ans1=0,ans2=0,cnt1=0,cnt2=0;
	for(int i=1;i<=m;i++) {
		x=(a*x+b)%(2*c*n);
		int id;
		if(x<n*c) {
			id=x/c+1;
			if(!f[id]) {
				f[id]=true;cnt1++,cnt2+=id;
			}
		} else {
			id=x/c-n+1;
			if(f[id]) {
				f[id]=false;cnt1--,cnt2-=id;
			}
		}
		ans1=(ans1+cnt1)%md,ans2=(ans2+cnt2)%md;
	}
	
	printf("%d %d",ans1,ans2);
	
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值