P9583 涂色 题解

P9583 涂色 题解

解法

题中说求最终有多少个方格涂着颜色,那我们可以求有多少个方格没有颜色,用方格的总数减去没有颜色的方格数即为所求。

考虑本题涂色规律,涂上 k k k 层颜料的方格其颜料会被擦去,这种操作的本质是对 k k k 取模,所以没有颜色的方格即该方格所在的行、列被涂色的次数和可以被 k k k 整除。

现在分别统计每个行、每个列的涂色次数,然后对行、列分别开两个桶,维护每行、每列的涂色次数对 k k k 取模后的值。

然后枚举桶里的元素。设有 r u b h i rubh_i rubhi 个行的涂色次数对 k k k 取模等于 i i i r u b l i rubl_i rubli 个列的涂色次数对 k k k 取模等于 i i i,则想要让一个方格没有颜色,则必须满足 h a n g i + l i e i ≡ 0 ( m o d k ) hang_i + lie_i \equiv 0 \pmod{k} hangi+liei0(modk),所以对于 r u b h i rubh_i rubhi 个行,只有 r u b l k − i rubl_{k-i} rublki 个列与之匹配才能是没有颜色的方格,根据乘法原理,有 r u b h i × r u b l k − i rubh_i \times rubl_{k-i} rubhi×rublki 个方格没有颜色。特殊地, r u b h 0 rubh_0 rubh0 r u b l 0 rubl_0 rubl0 匹配。

求解公式即为 r u b h 0 × r u b l 0 + ∑ i = 1 i < k r u b h i × r u b l k − i rubh_0 \times rubl_0 + \sum \limits _{i=1} ^{i < k} rubh_i \times rubl_{k-i} rubh0×rubl0+i=1i<krubhi×rublki,时间复杂度 O ( q + k ) \mathcal{O}(q + k) O(q+k)

代码

#include<bits/stdc++.h>
using namespace std;
namespace fast_IO
{
	/*
	快读快写
	*/
};
using namespace fast_IO;
int n,m,q,k,hang[200010],lie[200010],rubh[500010],rubl[500010];
inline void delh(int x)
{
	if(x==k-1) rubh[x]--,rubh[0]++;
	else rubh[x]--,rubh[x+1]++;
}
inline void dell(int x)
{
	if(x==k-1) rubl[x]--,rubl[0]++;
	else rubl[x]--,rubl[x+1]++;
}
long long ans;
int main()
{
	read(n),read(m),read(q),read(k),rubh[0]=n,rubl[0]=m;
	for(int i=1,op,x;i<=q;i++)
	{
		read(op),read(x);
		if(op==1) hang[x]++,delh((hang[x]-1)%k);
		else lie[x]++,dell((lie[x]-1)%k);
	}
	ans+=1ll*rubh[0]*rubl[0];
	for(int i=1;i<k;i++) ans+=1ll*rubh[i]*rubl[k-i];
	cout<<1ll*n*m-ans;
	return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值