安徽大学新生赛zzq和他的位运算

没什么好讲的,数位dp板子一套就好了

#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
#define int long long 
long long a[101],t[100][100],f[10];
long long dfs(int k,bool ok,int sum)
{
	if(k==0)//结束条件
	{
	return sum;
	}
	int end=ok?a[k]:1;//判断是否到达极值点
	long long s=0;//清零,初始化
	if(!ok&&t[k][sum]!=-1)return t[k][sum];//返回记忆化
	for(int i=0;i<=end;i++)//在每一个数位上从0搜到9,保证一个数不多,一个数不少。
	{
		s+=dfs(k-1,(ok)&&(i==end),(sum+i)%2);
        //把返回的每个数都加上,就是统计以搜到的这个数为前缀的符合条件的数的总数
        //递归,搜索下一个数位直到最后一位
	}
	if(!ok)t[k][sum]=s;//保存记忆化
	return s;//返回个数
}
long long chai(long long n)//把数拆开
{
	//if(n==0)return 0;
	memset(a,0,sizeof(a));
	memset(t,-1,sizeof(t));
	memset(f,0,sizeof(f));
    //初始化,全部清空
	int i=0;
	while(n!=0)//把数拆开,存在a数组里
	{
		i++;
		a[i]=n%2;
		n/=2;//把n分离每一个数位,直到n=0。一直把n/10
	}
	return dfs(i,1,0);
}
signed main()
{
	int t;cin>>t;
	for(int i=1;i<=t;i++)//这道题是要多次输入
	{
		long long n,m;//这道题一定要开longlong!!严重警告!!
		cin>>n>>m;
		cout<<chai(m)-chai(n-1)<<endl;
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值