一本通1649【例 2】2^k 进制数

1649:【例 2】2^k 进制数

时间限制: 1000 ms         内存限制: 524288 KB

【题目描述】

原题来自:NOIP 2006 提高组

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

1、r 至少是个 2 位的 2k 进制数。

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

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

在这里,正整数 k 和 w 是事先给定的。

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

【输入】

输入只一行,为两个正整数 k 和 w。

【输出】

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

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

【输入样例】

3 7

【输出样例】

36

【提示】

数据范围与提示:

对于所有数据,1k9,k<w3×104 。

 

sol:这道其实是道大水题

对于条件二很容易发现是个组合数,而且是严格小于,k的范围也不大,直接n2预处理组合数

统计答案是注意讨论首位是0和非0的情况

Ps:裸的高精貌似会MLE,建议压位

 

#include <bits/stdc++.h>
using namespace std;
typedef int ll;
inline ll read()
{
    ll s=0;
    bool f=0;
    char ch=' ';
    while(!isdigit(ch))
    {
        f|=(ch=='-'); ch=getchar();
    }
    while(isdigit(ch))
    {
        s=(s<<3)+(s<<1)+(ch^48); ch=getchar();
    }
    return (f)?(-s):(s);
}
#define R(x) x=read()
inline void write(ll x)
{
    if(x<0)
    {
        putchar('-'); x=-x;
    }
    if(x<10)
    {
        putchar(x+'0');    return;
    }
    write(x/10);
    putchar((x%10)+'0');
    return;
}
#define W(x) write(x),putchar(' ')
#define Wl(x) write(x),putchar('\n')
const int Base=10000,power=4;
int K,B,W;
struct Bignum
{
    int a[105];
    Bignum(){memset(a,0,sizeof a);}
    Bignum(int x)
    {
        memset(a,0,sizeof a);
        while(x)
        {
            a[++a[0]]=x%Base;
            x/=Base;
        }
        return;
    }
    inline void print()
    {
        int i;
        write(a[a[0]]);
        for(i=a[0]-1;i>=1;i--)
        {
            if(a[i]<1000) putchar('0');
            if(a[i]<100) putchar('0');
            if(a[i]<10) putchar('0');
            write(a[i]);
        }
        return;
    }
}C[515][515],ans;
#define P(x) x.print(),putchar(' ')
#define Pl(x) x.print(),putchar('\n')
inline Bignum operator+(const Bignum &p,const Bignum &q)
{
    int i;
    Bignum ans=p;
    for(i=1;i<=q.a[0];i++)
    {
        ans.a[i]+=q.a[i];
        ans.a[i+1]+=ans.a[i]/Base;
        ans.a[i]-=(ans.a[i]>=Base)?Base:0;
    }
    while(ans.a[ans.a[0]+1]) ans.a[0]++;
    return ans;
}
int main()
{
    int i,j;
    R(K); R(W);
    B=1<<K;
    C[0][0]=Bignum(1);
    for(i=1;i<=B;i++)
    {
        for(j=0;j<=B;j++)
        {
            C[i][j]=C[i][j]+C[i-1][j];
            if(j) C[i][j]=C[i][j]+C[i-1][j-1];
        }
    }
    int oo=W%K,Up=W/K;
    for(i=min(Up,B-1);i>=2;i--)
    {
        ans=ans+C[B-1][i];
    }
    if(oo)
    {
        int Last=(1<<oo)-1;
        for(i=1;i<=Last;i++) if((B-i-1)>=Up)
        {
            ans=ans+C[B-i-1][Up];
        }
        Pl(ans);
    }
    else
    {
        Pl(ans);
    }
    return 0;
}
/*
input
3 7
output
36

input
2 8
output
4
*/
View Code

 

转载于:https://www.cnblogs.com/gaojunonly1/p/10519836.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值