第 45 届国际大学生程序设计竞赛(ICPC)亚洲网上区域赛模拟赛 A-Easy Equation (差分优化枚举)

题目
题意很简单,就是要你求所有满足x + y + z = k的方案数。
直接一个个枚举的话太慢了,接近1e24。

我们考虑用差分去优化枚举。
怎么优化呢。

我们先来考虑x + y的得数情况,可以枚举x。
x + y的范围一定是在[x,x+b]的,也就是说,对于每个x来说,x + y的得数就是从 x ~ x + b的所有数,也就是这个区间都加上1,用差分来维护。
枚举一遍x之后就能得到一个x + y得数的差分数组,将差分数组做一个前缀和操作就能得到实际的每个得数的个数。
这是第一层差分数组。

之后,同样考虑(x + y)+ z的得数情况。
我们可以枚举 (x + y)。
(x + y)+ z的得数范围是在[x + y, x + y + c]的,但是注意对于每个(x + y)来说,x + y + z的得数就是之前第一层差分求得的 (x + y)的得数个数倍从(x + y)~ (x + y)+ c 的所有数,同样用差分来维护。
这是第二层差分数组。

然后将这个第二层的差分数组求前缀和,就能得到x + y + z的所有得数分别有多少个,这是最终的得数个数数组。

最后我们需要的答案就是遍历最终得数个数数组,将得数为 0 ~ d的所有个数加起来。

注意数据需要开long long。

#include<bits/stdc++.h>
#define ll long long
#define inf 0x3f3f3f3f
#define endl '\n'
#define IOS std::ios::sync_with_stdio(false),cin.tie(0), cout.tie(0)
using namespace std;

const int N = 6e6 + 10;

int a, b, c, d;
ll ans;
ll xy[N],xyz[N];

int main()
{
	IOS;
	cin >> a >> b >> c >> d; 
	for(int i = 0; i <= a; i ++)  //枚举a,+ b的所有情况。
	{
		xy[i] ++;
		xy[i + b + 1] --;    //i + y范围是从i 到 i + b 都有
							//一次,所以将这个范围都+1.
	}
	for(int i = 1; i <= a + b; i ++)  //得到x + y得数个数
		xy[i] += xy[i - 1];
	for(int i = 0; i <= a + b; i ++)
	{
						// i + z范围是从i 到 i + c 都有
						 // xy[i]次,所以将这个范围都+ xy[i]。
		xyz[i] += xy[i];   
		xyz[i + c + 1] -= xy[i];
	}
	for(int i = 1; i <= a + b + c; i ++)  //得到x+y+z得数个数
		xyz[i] += xyz[i - 1];
	for(int i = 0; i <= d; i ++)  
		ans += xyz[i];				//找到所有x+y+z == k 的
									//得数个数,并加进答案
	cout << ans << endl;
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值