二维反射容斥:P9366

https://www.luogu.com.cn/problem/P9366

构造循环矩阵,考虑反射容斥和将军饮马

在这里插入图片描述

考虑二维不太好做,我们曼哈顿距离转切比雪夫距离,变成一维的情况。

由于棋盘是正方形的,所以循环长度为 2 n + 4 2n+4 2n+4。用多项式快速幂预处理,询问记得考虑正负两个方向。

auto kuai(int T) {
	if(T==0) return atcoder :: Poly({1}); 
	auto p = kuai(T/2); 
	p *= p; 
	for(int i=M; i < p.size(); ++i) p[i-M]+=p[i]; 
	p = p.modxk(M); 
	
	if(T % 2 == 0) return p; 
	
	p = p.mulxk(1) + p.mulxk(M-1);  
	for(int i=M; i < p.size(); ++i) p[i-M]+=p[i]; 
	p = p.modxk(M); 
	
	return p; 
}


signed main()
{
//	freopen("in.txt", "r", stdin);
//	freopen("out.txt", "w", stdout);
//	T=read();
//	while(T--) {
//
//	}
	n=read(); T=read(); q=read(); 
	N=2*(n+1)+2; M=2*N; 
	auto res = kuai(T); 
	auto Go = [&] (int u0, int v0, int u1, int v1) {
		int dx = ( ((u1+v1) - (u0+v0)) % M + M)%M; 
		int dy = ( ((u1-v1) - (u0-v0)) % M + M)%M; 
//		printf("%lld %lld | %lld %lld\n", res[dx].x, res[dy].x, res[(dx+N)%M], res[(dy+N)%M]); 
		return res[dx] * res[dy] + res[(dx+N)%M] * res[(dy+N)%M]; 
	}; 
	while(q--) {
		u0 = read(); v0 = read(); 
		u1 = read(); v1 = read(); 
		auto ans = Go(u0, v0, u1, v1); 
		ans -= Go(u0, v0, N - 2 - u1, v1); 
		ans -= Go(u0, v0, u1, N - 2 - v1); 
		ans += Go(u0, v0, N - 2- u1, N - 2 - v1); 
		printf("%lld\n", ans.x); 
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值