zoukankan      html  css  js  c++  java
  • hdu5106 数位dp

    这题说的是给了一个二进制数R , 计算出 在[0,R) 区间内的数, 二进制中有n个1 个和

    n<=1000; R<2^1000, 这样 用dp[len][lee] 表示在第len位的时候已经放了lee个1 个总和, num[len][lee] 表示在第len位的时候已经放了lee个1 个数有多少个,这样只要考虑当前位置放1与不放1 记忆化进行搜索

    #include <iostream>
    #include <algorithm>
    #include <cstdio>
    #include <string.h>
    using namespace std;
    const int maxn =1005;
    typedef long long ll;
    const ll mod=1000000007;
    ll dp[maxn][maxn];
    ll num[maxn][maxn];
    char str[maxn];
    ll dig[maxn];
    void dfs(int loc, int lee , bool e, ll &value, ll &ge)
    {
           value = ge = 0;
           if(e==false&& num[loc][lee]!=-1 ){
               value=dp[loc][lee]; ge =num[loc][lee]; return ;
           }
           if(loc==0&&lee==0){
              value=0, ge=1; return ;
           }
           int we = e? str[loc-1]-'0':1;
           ll ans=0, nu=0;
           if(we==1){
               if(loc-1>=lee){
                   dfs(loc-1,lee,false,ans,nu);
                   value=ans, ge=nu;
               }
               if( lee > 0 ){
                   dfs(loc-1,lee-1,e,ans, nu);
                   value=( value + ans + ( dig[loc-1] )*nu%mod  )%mod;
                   ge = ( nu + ge )%mod;
               }
           }else{
               if(loc-1>=lee){
                dfs(loc-1,lee,e,ans,nu);
                value= ans; ge=nu;
               }
           }
        if(e==false) { dp[loc][lee] = value, num[loc][lee]=ge;  }
    }
    int main()
    {
        int n;
        dig[0]=1;
        for(int i=1; i<=1000; ++i)
            dig[i]=(dig[i-1]*2)%mod;
        while(scanf("%d%s",&n,str)==2){
            int len = strlen(str);
            for(int i=0; i<len/2; ++i){
                  char c = str[i];
                  str[i]=str[len-1-i];
                  str[len-1-i]=c;
            }
            memset(dp,0,sizeof(dp));
            memset(num,-1, sizeof(num));
            memset(num[0],0,sizeof(num[0]));
            num[0][0]=1;
            ll ans=0,nu=0;
            dfs( len , n , true, ans, nu);
             ll digt=0;nu=0;
            for(int i=0; i<len; ++i){
                 if(str[i]=='1'){
                     digt++; nu= ( nu + dig[i])%mod;
                 }
            }
                 if(digt==n) ans=(ans-nu+mod)%mod;
            printf("%I64d
    ",ans);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    通过java代码获取jvm信息和系统信息
    java cp与java jar的区别
    vue下实现WebRTC
    MANIFEST.MF文件详解
    element 前端排序 与 后端排序
    JAVA获取CPUID、主板序列号、硬盘序列号、MAC地址(自己验证过)
    PHP常用代码大全
    程序员从初级到中级10个秘诀
    移动平台还有哪些创业机会
    程序员招聘:如何识别真正的程序员
  • 原文地址:https://www.cnblogs.com/Opaser/p/4114726.html
Copyright © 2011-2022 走看看