• UVALive 4864 数位dp


    Start with an integer, N0, which is greater than 0. Let N1 be the number of ones in the binary representation of N0. So, if N0 = 27, N1 = 4. For all i > 0, let Ni be the number of ones in the binary representation of Ni-1. This sequence will always converge to one. For any starting number, N0, let K be the minimum value of i 0 for which Ni = 1. For example, if N0 = 31, then N1 = 5, N2 = 2, N3 = 1, so K = 3.

    Given a range of consecutive numbers, and a value X, how many numbers in the range have a K value equal to X?

    64位同时为1时即转换为了64以下的数转换到1的步数,所以首先打个表,之后枚举数位之和就ok了。

    View Code
     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<cstdlib>
     5 using std::cout;
     6 using std::cin;
     7 using std::endl;
     8 typedef long long LL;
     9 int const N = 64;
    10 int step[N],bit[N+10],ln;
    11 LL lo,hi;
    12 int x;
    13 LL dp[N][N][2];
    14 int getsum1(int n)
    15 {
    16     int sum=0;
    17     int num=n;
    18     for(;n;sum+=n%2,n>>=1);
    19     if(sum==1)return 1;
    20     if(step[sum])return step[sum]+1;
    21     step[num]=getsum1(sum)+1;
    22 }
    23 void pre()
    24 {
    25      step[1]=0;
    26      for(int i=2;i<=64;i++)
    27      {
    28          if(!step[i])
    29             step[i]=getsum1(i);
    30      }
    31 }
    32 LL getsum2(int t,int pre,int rest,int limit)
    33 {
    34    if(rest<0)return 0;
    35    if(!t)return (rest==0);
    36    int up=(limit?bit[t]:1);
    37    LL ans=0;
    38    if(!limit&&dp[t][rest][pre]!=-1)return dp[t][rest][pre];
    39    for(int i=0;i<=up;i++)
    40    {
    41        ans+=getsum2(t-1,i,rest-i,limit&&i==up);
    42    }
    43    if(!limit&&dp[t][rest][pre]==-1)dp[t][rest][pre]=ans;
    44    return ans;
    45 }
    46 LL getsum3(LL n)
    47 {
    48    if(n<=0)return 0;
    49    for(ln=0;n;bit[++ln]=n%2,n>>=1);
    50    LL ans=0;
    51    if(x==0)
    52    return 1;
    53    if(x==step[1]+1)
    54    ans+=getsum2(ln,0,1,1)-1;
    55    for(int i=2;i<=ln;i++)
    56        if(x==step[i]+1)
    57           ans+=getsum2(ln,0,i,1);
    58    return ans;
    59 }
    60 int main()
    61 {
    62     pre();
    63     memset(dp,-1,sizeof(dp));
    64     while(scanf("%lld %lld",&lo,&hi))
    65     {
    66           scanf("%d",&x);
    67           if(!(x+lo+hi))break;
    68           printf("%lld\n",getsum3(hi)-getsum3(lo-1));
    69     }
    70     return 0;
    71 }
  • 相关阅读:
    【转载】面对酱紫的情况,肿么办哇?
    webform 基础
    LINQ 语句实现分页
    LINQ to SQL 语句
    发送邮件&Timer
    treeview递归
    进程&线程
    登录框记住账号
    窗体-对话框,记事本
    日期与地区的三级联动
  • 原文地址:https://www.cnblogs.com/nuoyan2010/p/3067186.html
Copyright © 2020-2023  润新知