zoukankan      html  css  js  c++  java
  • 洛谷P1066 2^k进制数

    P1066 2^k进制数

    题目描述

    设r是个2^k 进制数,并满足以下条件:

    (1)r至少是个2位的2^k 进制数。

    (2)作为2^k 进制数,除最后一位外,r的每一位严格小于它右边相邻的那一位。

    (3)将r转换为2进制数q后,则q的总位数不超过w。

    在这里,正整数k(1≤k≤9)和w(k<W< span>≤30000)是事先给定的。

    问:满足上述条件的不同的r共有多少个?

    我们再从另一角度作些解释:设S是长度为w 的01字符串(即字符串S由w个“0”或“1”组成),S对应于上述条件(3)中的q。将S从右起划分为若干个长度为k 的段,每段对应一位2^k进制的数,如果S至少可分成2段,则S所对应的二进制数又可以转换为上述的2^k 进制数r。

    例:设k=3,w=7。则r是个八进制数(23=8)。由于w=7,长度为7的01字符串按3位一段分,可分为3段(即1,3,3,左边第一段只有一个二进制位),则满足条件的八进制数有:

    2位数:高位为1:6个(即12,13,14,15,16,17),高位为2:5个,…,高位为6:1个(即67)。共6+5+…+1=21个。

    3位数:高位只能是1,第2位为2:5个(即123,124,125,126,127),第2位为3:4个,…,第2位为6:1个(即167)。共5+4+…+1=15个。

    所以,满足要求的r共有36个。

    输入输出格式

    输入格式:

    输入只有1行,为两个正整数,用一个空格隔开:

    k W

    输出格式:

    输出为1行,是一个正整数,为所求的计算结果,即满足条件的不同的r的个数(用十进制数表示),要求最高位不得为0,各数字之间不得插入数字以外的其他字符(例如空格、换行符、逗号等)。

    (提示:作为结果的正整数可能很大,但不会超过200位)

    输入输出样例

    输入样例#1:
    3 7
    输出样例#1:
    36

    说明

    NOIP 2006 提高组 第四题

    第一类:位数为2—len-1的2k 进制数种数; 它等于从2k -1个数中分别不重复地取2个、3个、…….len-1个数的不同组合数之和,C(2k-1,i)

    注意这里的i不仅要小于w/k,还要小于maxk

    第二类:位数已经达到len的2k 进制数种数; 这类数的首位可能够是1,2,……2k-i-1,从第2位开始取数时每次都要扣除小于左边相邻数的这些数,因此可供选择的数越来越少,累加起来是∑c(2k –(i+1),len),(1<=i<=2k )。

    注意这里的i不仅要小于maxq,还要保证需要的数字数不能大于剩下可选的数字数

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    int a[205],b[205],c[205];
    struct node{
        int zu[205],len;
        node operator + (const node x)const{
            memset(c,0,sizeof(c));
            memset(a,0,sizeof(a));
            memset(b,0,sizeof(b));
            for(int i=1,j=len;i<=len;i++,j--)a[i]=zu[j];
            for(int i=1,j=x.len;i<=x.len;i++,j--)b[i]=x.zu[j];
            int l=max(x.len,len);
            for(int i=1;i<=l;i++){
                c[i]+=a[i]+b[i];
                c[i+1]+=c[i]/10;
                c[i]=c[i]%10;
            }
            while(c[l+1]){
                l++;
                c[l+1]+=c[l]/10;
                c[l]%=10;
            }
            node res;res.len=l;
            for(int i=1,j=l;i<=l;i++,j--)res.zu[i]=c[j];
            return res;
        }
    }f[515][515];
    void prepare(){
        for(int i=0;i<=510;i++)
            for(int j=0;j<i;j++){
                if(j==0||i==j){f[i][j].len=1;f[i][j].zu[1]=1;}
                else f[i][j]=f[i-1][j]+f[i-1][j-1];
            }
    }
    int main(){
        freopen("Cola.txt","r",stdin);
        node ans;ans.len=0;
        prepare();
        int k,w;
        scanf("%d%d",&k,&w);
        int maxk=(1<<k);
        int p=w/k,q=w-p*k;
        int maxq=(1<<q);
        for(int i=2;i<=p&&i<maxk;i++)ans=ans+f[maxk][i];    
        for(int i=1;i<=maxq-1&&p+i<maxk;i++)ans=ans+f[maxk-i][p];
        for(int i=1;i<=ans.len;i++)printf("%d",ans.zu[i]);
    }
  • 相关阅读:
    06 is和==的区别 encode()编码 decode()解码
    05 dic的增删改查 字典的嵌套 考试题dic.get()的相关使用
    03 编码 int ,bool,str的常用操作 主要讲str
    01 基本数据类型 变量 if语句
    04 列表的增删改查 常用方法 元祖 range
    02 while循环 格式化输出 运算符
    多校2 Harmonious Army hdu6598 网络流
    P3159 [CQOI2012]交换棋子 网络流
    P2172 [国家集训队]部落战争 最大流
    P2402 奶牛隐藏 网络流
  • 原文地址:https://www.cnblogs.com/thmyl/p/7674221.html
Copyright © 2011-2022 走看看