[1545] New Year 2014

  • [1545] 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的思路倒是很容易的就想出来了,但是没想到一个小细节,让我查了一天的数据,。。。

#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
__int64 dp1[16][20],dp2[16][20];
char s1[20],s2[20];
int main()
{
    //freopen("data.in","r",stdin);
    memset(dp1,0,sizeof(dp1));
    memset(dp2,0,sizeof(dp2));
    for(int i=0;i<=9;i++)
    {
        dp1[i][1] = dp2[i][1] = 1;
    }
    dp1[0][0] = dp2[0][0] = 1;
    for(int i=2;i<=19;i++)
    {
        for(int j=1;j<=9;j++)
        {
            for(int k = 0;k<=15;k++)
            {
                int u = k^j;
                dp1[u][i]+=dp2[k][i-1];  //不带前导0
            }
        }
        for(int j=0;j<=9;j++)
        {
            for(int k=0;k<=15;k++)
            {
                int u = k^j;
                dp2[u][i]+=dp2[k][i-1];   //带前导0
            }
        }
    }
    while(scanf("%s %s",s1,s2)!=EOF)
    {
        int l2 = strlen(s2);
        int l1 = strlen(s1);
        if(l2>2)
        {
            printf("0\n");
            continue;
        }
        int s= 0;
        for(int i=0;i<=l2-1;i++)
        {
            s = s*10+s2[i]-'0';
        }
        if(s>15)
        {
            printf("0\n");
            continue;
        }
        __int64 res = 0;
        for(int i=1;i<=l1-1;i++)
        {
            res+=dp1[s][i];
        }
        int tag = 0;
        for(int i=0;i<=l1-1;i++)
        {
            int dig = s1[i]-'0';
            int t;
            if(i==0)
            {
                t =1;
            }else
            {
                t = 0;
            }
            for(int j=t;j<=dig-1;j++)
            {
                for(int k=0;k<=15;k++)
                {
                    int x = tag^j;
                    x = x^k;
                    if(x==s)
                    {
                        res+=dp2[k][l1-1-i];
                    }
                }
            }
            tag = tag^dig;
        }
        if(l1==1&&s==0)
        {
            res++;
        }else
        {
            tag = 0;
            for(int i=0;i<=l1-1;i++)
            {
                int dig = s1[i]-'0';
                tag = tag^dig;
            }
            if(tag==s)
            {
                res++;
            }
        }
        if(s==0)
        {
            res-=1;
        }
        printf("%I64d\n",res);
    }
    return 0;
}


 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值