版权声明:本文为蒟蒻所写,神犇转载尽情拍打喂食虐待,如发现任何的辣鸡错误欢迎吐槽! https://blog.csdn.net/HOWARLI/article/details/82946718
Description
Solution
把题目容斥一下,
假设当前求x在0 ~ l1中和y在0~ l2中的答案,
显然的,当x,y的取值均为2的次方时,答案是很好求的,
考虑怎么转成这样:
那么我们枚举l1的一位为1的二进制i,枚举l2的一位为1的二进制j,
我们使得x的前i-1位为二进制跟l1相同,第i位为0,那么x剩下二进制位的取值就自由了,也就是0 ~
y也同理,那么我们就成功吧题目转成了x,y均为2的次方的情况,
复杂度:
Code
#include <cstdio>
#include <algorithm>
#include <iostream>
#define fo(i,a,b) for(int i=a;i<=b;++i)
#define fod(i,a,b) for(int i=a;i>=b;--i)
#define efo(i,q) for(int i=A[q];i;i=B[i][0])
#define min(q,w) ((q)>(w)?(w):(q))
#define max(q,w) ((q)<(w)?(w):(q))
using namespace std;
typedef long long LL;
const int N=100500,mo=998244353;
int read(int &n)
{
char ch=' ';int q=0,w=1;
for(;(ch!='-')&&((ch<'0')||(ch>'9'));ch=getchar());
if(ch=='-')w=-1,ch=getchar();
for(;ch>='0' && ch<='9';ch=getchar())q=q*10+ch-48;n=q*w;return n;
}
LL ans;
LL l1,r1,L1,R1,M;
LL er[100];
LL doit(LL n,LL m)
{
n=max(n,0);m=max(m,0);
LL ans=0;
fod(i,62,1)if(er[i]&n)
{
fod(j,62,1)if(er[j]&m)
{
LL t=((n&(er[63]-1-er[i+1]+1))^(m&(er[63]-1-er[j+1]+1)))&(er[63]-1-er[max(i,j)]+1);
ans=(ans+er[min(i,j)]%mo*(((t+er[max(i,j)]-1)/M-(max(t,1)-1)/M+(t==0))%mo))%mo;
}
}
fod(i,62,1)if(er[i]&n)
{
LL l=((n&(er[63]-1-er[i+1]+1))^m)&(er[63]-1-er[i]+1);
LL r=l|(er[i]-1);
ans=(ans-((l-1)/M)+r/M)%mo;
if(l==0)++ans;
}
fod(i,62,1)if(er[i]&m)
{
LL l=(n^(m&(er[63]-1-er[i+1]+1)))&(er[63]-1-er[i]+1);
LL r=l|(er[i]-1);
ans=(ans-((l-1)/M)+r/M)%mo;
if(l==0)++ans;
}
if((n^m)%M==0)++ans;
return ans;
}
int main()
{
freopen("mod.in","r",stdin);
freopen("mod.out","w",stdout);
int q,w;
scanf("%lld%lld%lld%lld%lld",&l1,&r1,&L1,&R1,&M);
er[1]=1;fo(i,2,63)er[i]=er[i-1]<<1;
ans=doit(r1,R1)-doit(l1-1,R1)-doit(r1,L1-1)+doit(l1-1,L1-1);
printf("%lld\n",(ans%mo+mo)%mo);
return 0;
}