• Codeforces 914C Travelling Salesman and Special Numbers:数位dp


    题目链接:http://codeforces.com/problemset/problem/914/C

    题意:

      对数字x进行一次操作,可以将数字x变为x在二进制下1的个数。

      显然,一个正整数在进行了若干次操作后一定会变成1。

      给定n,k(n用二进制表示给出,n <= 2^1000)。

      问你有多少不超过n的正整数,将它们变为1所需的操作次数恰好为k。

    题解:

      由于n <= 2^1000,所以任何不超过n的数在进行了一次操作后,一定不超过1000。

      所以先统计出1000以内所有数变成1所需的操作次数:f[i] = f[cal_bit(i)] + 1

      那么最终答案 = ∑(恰好包含i个1,且不超过n的数字个数),其中f[i] == k-1。

      所以接下来就要求恰好包含i个1,且不超过n的数字个数:

        表示状态:

          dp[i][j][0/1]表示已经填了前i位数,用了j个1,是否与n匹配(0/1),此时的方案数。

          (n的最高位为第1位)

        找出答案:

          恰好包含i个1,且不超过n的数字个数 = dp[n][i][0] + dp[n][i][1]

        如何转移:

          对于dp[i][j][0]:

            dp[i+1][j][0] += dp[i][j][0]

            dp[i+1][j+1][0] += dp[i][j][0]

          对于dp[i][j][1]:

            如果n的第i+1位为1:

              dp[i+1][j][0] += dp[i][j][1]

              dp[i+1][j+1][1] += dp[i][j][1]

            否则:

              dp[i+1][j][1] += dp[i][j][1]

        边界条件:

          dp[1][0][0] = dp[1][1][1] = 1

     

        最后统计下答案就好。

        其中k==0或1的情况要特判。

    AC Code:

      1 #include <iostream>
      2 #include <stdio.h>
      3 #include <string.h>
      4 #define MAX_N 1005
      5 #define MOD 1000000007
      6 
      7 using namespace std;
      8 
      9 int n,k;
     10 int ans=0;
     11 int a[MAX_N];
     12 int f[MAX_N];
     13 int dp[MAX_N][MAX_N][2];
     14 string s;
     15 
     16 void read()
     17 {
     18     cin>>s>>k;
     19     n=s.size();
     20     for(int i=0;i<n;i++) a[i+1]=s[i]-'0';
     21 }
     22 
     23 int cal_bit(int x)
     24 {
     25     int cnt=0;
     26     int lowbit=x&-x;
     27     while(lowbit)
     28     {
     29         cnt++;
     30         x^=lowbit;
     31         lowbit=x&-x;
     32     }
     33     return cnt;
     34 }
     35 
     36 void cal_f()
     37 {
     38     f[1]=0;
     39     for(int i=2;i<=1000;i++)
     40     {
     41         f[i]=f[cal_bit(i)]+1;
     42     }
     43 }
     44 
     45 void cal_dp()
     46 {
     47     memset(dp,0,sizeof(dp));
     48     dp[1][0][0]=dp[1][1][1]=1;
     49     for(int i=1;i<n;i++)
     50     {
     51         for(int j=0;j<=i;j++)
     52         {
     53             if(dp[i][j][0])
     54             {
     55                 dp[i+1][j][0]+=dp[i][j][0];
     56                 dp[i+1][j+1][0]+=dp[i][j][0];
     57                 dp[i+1][j][0]%=MOD;
     58                 dp[i+1][j+1][0]%=MOD;
     59             }
     60             if(dp[i][j][1])
     61             {
     62                 if(a[i+1])
     63                 {
     64                     dp[i+1][j][0]+=dp[i][j][1];
     65                     dp[i+1][j+1][1]+=dp[i][j][1];
     66                     dp[i+1][j][0]%=MOD;
     67                     dp[i+1][j+1][1]%=MOD;
     68                 }
     69                 else
     70                 {
     71                     dp[i+1][j][1]+=dp[i][j][1];
     72                     dp[i+1][j][1]%=MOD;
     73                 }
     74             }
     75         }
     76     }
     77 }
     78 
     79 void cal_ans()
     80 {
     81     for(int i=1;i<=1000;i++)
     82     {
     83         if(f[i]==k-1)
     84         {
     85             ans+=dp[n][i][0]+dp[n][i][1];
     86             ans%=MOD;
     87         }
     88     }
     89 }
     90 
     91 void work()
     92 {
     93     if(k==0)
     94     {
     95         cout<<1<<endl;
     96         return;
     97     }
     98     cal_f();
     99     cal_dp();
    100     cal_ans();
    101     if(k==1) cout<<ans-1<<endl;
    102     else cout<<ans<<endl;
    103 }
    104 
    105 int main()
    106 {
    107     read();
    108     work();
    109 }
  • 相关阅读:
    TCP握手建立与释放连接
    Oracle Golden Gate概要
    Hadoop Spark 基础教程
    #npm install# MSBUILD : error MSB4132: 无法识别工具版本“2.0”。可用的工具版本为 "4.0"。
    MySQL5.7 不同操作系统下的主从配置
    MongoDB authentication failed
    maven相关基础
    一次失败的定点漏洞挖掘之代码审计宜信Davinci
    记一次在tp5代码执行下的pcntl_exec瞎操作
    【CVE-2020-1957】shiro搭配spring时身份验证绕过漏洞分析
  • 原文地址:https://www.cnblogs.com/Leohh/p/8461007.html
Copyright © 2020-2023  润新知