AtCoder Beginner Contest 138 F - Coincidence

首先对 x,y 进行分类讨论(二进制形式)

         1)    y   1??????

                x   0??????

           ------------------------------

        y xor x   1???????

      y mod x   0?????? 

 

不符合条件,对各种条件分类得知 只有以下情况符合题意

       y   1??????

       x   1??????

      则此时 x<=y<2x

      所以   y\, mod\, x=y\, -\, x   推得  y\,mod\,x=y-x=y\,xor\,x     ……………… (1)式

 

下面证明结论: y ^ x = y+x - 2 * (y & x)

                         考虑 y,x的每一位的值,共有四种情况

                         分类易知,(1,1)时的进位恰好被 2*(y&x) 减去

      将该结论代入 (1)式,得到  y-x = y+x- 2*(y&x) 

      即 x = x & y

所以问题转化为:求  L<=x<=y<=R 中 有多少对 (x,y)满足  x = x&y

利用dp解决 (虽然我觉得我状态设计太多)

代码如下,注释在程序中:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

const int mod=1e9+7;

ll L,R;

ll f[64][2][2][2][2];
int l[100],r[100];

ll dfs(int x,int fl,int fr,int s,int ht)
{
	if(x<0)return 1;
	// x:第x位 (二进制转十进制下权值是1的为第0位)
	// fl: y之前是否有填过小于 R的某一位的数字   例如:R:11000 y:10??? fl即为1 表示后面数字可以往大了填 
	// fr: x之前是否有填过大于 L的某一位的数字   类似fl
	// s: 之前x是否有某一位 < y的某一位 如果有,后面的位数就没有相对大小限制了 (确保 x<=y)
	//ht:确保 x,y 最高位一样都为1  (满足推导的要求) 
	ll &ans=f[x][fl][fr][s][ht];
	if(ans)return ans;
	
	for(int i=0;i<2;i++)//y
	{
		for(int j=0;j<2;j++)//x
		{
			int tl=fl,tr=fr,ts=s,tt=ht;
			if(!tt&&i)if(i!=j)continue;
			if((j&i)!=j)continue;
			if(!tl&&j<l[x])continue;
			if(!tr&&i>r[x])continue;
			if(!ts&&j>i)continue;
			if(j>l[x])tl=1;if(i<r[x])tr=1;if(j<i)ts=1;if(j)tt=1;
			ans+=dfs(x-1,tl,tr,ts,tt);
		}
	}
	ans%=mod;
	return ans;
}

int main()
{
	ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
	
	cin>>L>>R;
	for(int i=63;i>=0;i--)
	{
		l[i]=(bool)((1ll<<i)&L);r[i]=(bool((1ll<<i)&R));
	}
	
	cout<<dfs(63,0,0,0,0);
	
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值