JZOJ5894【NOIP2018模拟10.5】同余方程

题目

Description

在这里插入图片描述

Input

在这里插入图片描述

Output

在这里插入图片描述

Sample Input

123 1234 234 2345 5

Sample Output

470244

Data Constraint

在这里插入图片描述

题目大意

求满足(xy)mod  m=0(x \bigoplus y) \mod m=0x,yx,y个数,其中x(l1,r1)  y(l2,r2)x \in (l_1,r_1)\ \ y \in (l_2,r_2)


思考历程

一眼望去,毫无头绪……
异或会和取模有什么关系?
想半天,拿了30分暴力,便弃之。

正解

没错,异或和取模的确没有什么关系。
所以不要认为是什么奇葩数论题。

正确的思路是将其分成许多段连续的区间,然后直接计算贡献。
那么怎么划分?
首先,我们可以将ll先当成11。因为只要求出这个情况的答案,那么就可以通过二维前缀和的方式算出整一题的答案。
对于上界xxyy,分别枚举它们为11的位数(作为第一个小于上界的位)。
设这两个位数分别为iijj
如果比ii高的位不变,将ii设为00,那么比ii低的位无论如何取值,都不可能超过上限。
mx=max(i,j)  mn=min(i,j)mx=\max(i,j) \ \ mn=\min(i,j)
我们可以将两者异或起来的结果分为三段。
首先是最高位到mxmx位,这些位的异或结果是固定的。
然后mxmxmnmn位,在这里的异或结果可以是任意的,并且每一个异或结果对应着唯一的一种方案。
最后是mnmn到最低位,这里的异或结果也是任意的,并且每一个异或结果对应着2mn2^{mn}种方案。
异或的结果的取值范围为[t,t+2mx)[t,t+2^{mx}),t为前面已经确定的异或结果。
这样就可以直接通过除法算出这段区间的贡献了。

(t+2mx1mt1m)2mn\left(\lfloor \frac{t+2^{mx}-1}{m} \rfloor-\lfloor \frac{t-1}{m} \rfloor\right)2^{mn}
还有,求tt的时候有一点需要注意:
tt已经确定的部分是mxmx及之前的部分,而对于mxmx为要特殊处理一下。
如果i=ji=j,那么mxmx位中两者都是11,异或起来为00,相当于000 \bigoplus 0,不理它。
如果iji \neq j,由于mxmx位需要修改成00,所以需要将mxmx为取个反。
详见一下代码。


代码

using namespace std;
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#define mod 998244353
long long l1,r1,l2,r2,m;
long long ans(long long,long long);
int main(){
	freopen("mod.in","r",stdin);
	freopen("mod.out","w",stdout);
	scanf("%lld%lld%lld%lld%lld",&l1,&r1,&l2,&r2,&m);
	printf("%lld\n",(ans(r1,r2)-ans(l1-1,r2)-ans(r1,l2-1)+ans(l1-1,l2-1)+mod+mod)%mod);
	return 0;
}
long long ans(long long x,long long y){
	x++,y++;
	long long res=0; 
	for (int i=59;i>=0;--i)
		if (x>>i&1)
			for (int j=59;j>=0;--j)
				if (y>>j&1){
					int mx=max(i,j),mn=i+j-mx;
					long long cur=(x^y^((i==j)?0:1ll<<mx))>>mx<<mx;//具体解释见上,还有后面的右移左移是为了将后面的东西清除掉
					if (cur==0)
						res=(res+(((1ll<<mx)-1)/m+1)%mod*((1ll<<mn)%mod)%mod)%mod;//当cur=0时,(cur-1)为负数,所以(cur-1)/m会上取整……所以直接特判
					else
						res=(res+(((cur+(1ll<<mx)-1)/m-(cur-1)/m)%mod+mod)%mod*((1ll<<mn)%mod)%mod)%mod;
				}
	return res;
}
posted @ 2018-10-07 15:33  jz_597  阅读(116)  评论(0编辑  收藏  举报