Fighting For 2014 (One University One Question) Round II [E] New Year 2014

13 篇文章 0 订阅
4 篇文章 0 订阅

  • [E] New Year 2014

  • 时间限制: 2000 ms 内存限制: 262144 K
  • 问题描述
  • In the New Year 2014, Xiao Ming is thinking about the question: give two integers N and K, Calculate the number of the numbers of satisfy the following conditions:

    1. It is a positive integer and is not greater than N.

    2. Xor value of its all digital is K.

    For example N = 12, K = 3, the number of satisfy condition is 3 and 12 (3 = 3, 1 ^ 2 = 3).

    In order to let Xiao Ming happy in the New Year 2014, can you help him?

  • 输入
  • There are multiple test cases, each test sample contains two positive integers N and K (0 <= N, K < 10 ^ 18), End to file.
  • 输出
  • For each case, output the number of the numbers of satisfy condition in one line.
  • 样例输入
  • 12 3
    999 5
    12354 8
  • 样例输出
  • 2
    76
    662
  • 提示
  • 来源
  • 宁静致远 @HBMY
  • 操作

很久没做题了,对于这种最简单的数位dp都做不了!

题意:求1~n的数中符合每一数位的异或为k的个数。

题解:最简单的数位dp,不过要懂得a = b1^b2^……bm   推出  a^b1^b2……bm = 0;

所以我们dfs时dp[i][j]代表着选择了i位和前i位异或值为j的个数(剩下的全排列所有情况)。

然后就一步步递归下去。。

不过这些都是包括零,所以还要减去0.。

#include<cstdio>
#include<cstring>
#include<math.h>
#include<algorithm>
#include<vector>
#include<queue>
#include<iostream>
#include<cstdlib>

using namespace std;

int Max(int a,int b)
{
	return a>b?a:b;
}
long long dp[25][20];
long long n,k;
int num[20];
int tran(long long n)
{
	int i = 0;
	while(n)
	{
		num[i++] = n%10;
		n/=10;
	}
	return i;
}
long long DFSdp(int b,int s,int r,int doing)
{
	
	if(b==0 ) 
	{
		if(r==0)
			return 1;
		else
			return 0;
	}
	if(!doing && dp[b][r]!=-1) 
	{
		return dp[b][r];
	}
	int end = doing==1?num[b-1]:9;
	long long ans = 0;
	for(int i=0;i<=end;i++)
	{
		ans += DFSdp(b-1,i,r^i,doing&&i==end);
	}
	if(!doing)
		dp[b][r] = ans;
	return ans;
}
int main()
{
	memset(dp,-1,sizeof(dp));
	
	while(~scanf("%lld%lld",&n,&k))
	{
		int b = tran(n);
		if(k>15) 
		{
			printf("0\n");
			continue ;
		}
		long long ans = DFSdp(b,0,(int)k,1);
		if(k==0)
			ans--;
		printf("%lld\n",ans);
	}
	
    return 0;
}



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值