题目链接

题目描述

设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≤30000)是事先给定的。

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

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

例:设k=3,w=7。则r是个八进制数(2^3=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位)

样例输入

3 7

样例输出

36

分析:

这是一个组合数学问题,

注意这句话:作为2^k 进制数,除最后一位外,r的每一位严格小于它右边相邻的那一位。

其实这是在暗示组合数,

显然r中的不会有相同的位,如果每一位都不同,显然只有严格递增的排列是合法的,这便是组合,

将 r 转化成这种形式(设k为3) 000 000 000 000

显然除首位外每一位的取值范围为 000 to 111(2^k-1)

在首位为0的情况下,最多可取 w/k 位,且题目要求大于2位,

则在首位为0的合法解有 ∑ C(2^k-1,i)(2<=i<=w/k) ,

Ps. 如果 w 模 k 等于 0 仅考虑上述情况即可。

考虑首位不为0的情况,显然首位不为0的话,r 就有 w/k+1 位,

除首位外还有w/k位,可以枚举首位的取值范围为 1 to 2^(w mod k)-1

设首位取值为 val,则剩下 w/k 位 取值范围为 val+1 to 2^k-1,也就是有 2^k-1-val 个数可取,所以首位不为0的合法解有 ∑ C(2k-1-val,w/k)(1<=val<=2(w mod k)-1)

所以上述两者相加便是正解(需要高精运算)

对于高精运算的处理,我看到了一个比较巧妙的方法避开了复杂的数组运算,就是把上面那些组合数的运算

都转换成了 C(2^k-1,i) -----> C(2^k-i,i) 然后写C函数的时候不是计算C(2k-1,i),而是计算C(2k-i+i-1,i)。 巧妙之处就在这里,这样可以有效的避免有溢出吧。

注意事项:

1、本题的关键就是看懂题目,知道这是个排列组合问题。

2、在排列组合的计算时,用了一个巧妙的方法,希望能看懂。

代码:

#include <iostream>
#include <cmath>
#include<stdio.h>
using namespace std;
long C(int n,int m) //公式为C(n+m-1)(m)[重点] 希望结合上面说的看懂
{
int i;
long sum=1;
for (i=1;i<=m;i++)
sum*=(n+m-i);
for (i=1;i<=m;i++)
sum=sum/i;
return sum;
}
int main()
{
int k, w;
cin >> k >> w;
int part_num = w / k + 1; //一共分为几段
int maxx_num_per_part = pow(2.0,k); //取不到,每部分最大取到maxx_num_per_part减去1,就是每一位都是1的时候
int gaow_num_max = pow(2.0,w%k) - 1; //最高位的数最大值,可以是0
//开始计算,分两种情况,第一种,首段为0,那么后面n位数对应的个数符合C[maxx_num_per_part-1][n]
long long sum = 0;
for (int i=2; i<=part_num-1; i++) //去掉最高位部分,还有至少两位数
{
sum += C(maxx_num_per_part-i, i);
}
//第二种情况,首段不是0,如果首段为x,解就有C[maxx_num_per_part-1-x][w/k]
for (int i=1; i<=gaow_num_max; i++)
{
sum += C(maxx_num_per_part-w/k-i,w/k);
}
cout << sum;
return 0;
}

蓝桥杯 问题 1110: 2^k进制数 (排列组合+高精度巧妙处理)的更多相关文章

  1. [蓝桥杯]ALGO-16.算法训练_进制转换

    问题描述 我们可以用这样的方式来表示一个十进制数: 将每个阿拉伯数字乘以一个以该数字所处位置的(值减1)为指数,以10为底数的幂之和的形式.例如:123可表示为 1*102+2*101+3*100这样 ...

  2. Java实现 蓝桥杯VIP 算法训练 -2进制(暴力)

    试题 算法训练 -2进制 问题描述 给出1个十进制整数N,计算出它的-2进制表示. 输入格式 第一行:一个整数N,表示要转换的十进制数. 输出格式 第一行:N的-2进制表示. 样例输入 -13 样例输 ...

  3. Java实现 蓝桥杯VIP 算法训练 ALGO-16进制转换

    算法训练 进制转换 时间限制:1.0s 内存限制:256.0MB 问题描述 我们可以用这样的方式来表示一个十进制数: 将每个阿拉伯数字乘以一个以该数字所处位置的(值减1)为指数,以10为底数的幂之和的 ...

  4. Java实现 蓝桥杯VIP 算法训练 ALGO-85进制转换

    问题描述 编写一个程序,输入一个二进制的字符串(长度不超过32),然后计算出相应的十进制整数,并把它打印出来. 输入格式:输入为一个字符串,每个字符都是'0'或'1',字符串的长度不超过32. 输出格 ...

  5. k进制正整数的对k-1取余与按位取余

    华电北风吹 天津大学认知计算与应用重点实验室 日期:2015/8/24 先说一下结论 有k进制数abcd,有abcd%(k−1)=(a+b+c+d)%(k−1) 这是由于kn=((k−1)+1)n=∑ ...

  6. [转]as3 算法实例【输出1 到最大的N 位数 题目:输入数字n,按顺序输出从1 最大的n 位10 进制数。比如输入3,则输出1、2、3 一直到最大的3 位数即999。】

    思路:如果我们在数字前面补0的话,就会发现n位所有10进制数其实就是n个从0到9的全排列.也就是说,我们把数字的每一位都从0到9排列一遍,就得到了所有的10进制数. /** *ch 存放数字 *n n ...

  7. 1813. M进制数问题

    1813. M进制数问题 Constraints Time Limit: 1 secs, Memory Limit: 32 MB Description 试用 C++的类来表示一般进制数. 给定 2 ...

  8. CF459C Pashmak and Buses (构造d位k进制数

    C - Pashmak and Buses Codeforces Round #261 (Div. 2) C. Pashmak and Buses time limit per test 1 seco ...

  9. [codevs1157]2^k进制数

    [codevs1157]2k进制数 试题描述 设r是个2k 进制数,并满足以下条件: (1)r至少是个2位的2k 进制数. (2)作为2k 进制数,除最后一位外,r的每一位严格小于它右边相邻的那一位. ...

随机推荐

  1. PAT甲题题解-1117. Eddington Number(25)-(大么个大水题~)

    如题,大水题...贴个代码完事,就这么任性~~ #include <iostream> #include <cstdio> #include <algorithm> ...

  2. [Docker基础]如何清除不用的资源

    Docker - How to cleanup resources 有时你可能需要清理Docker中不用的资源,特别是在学习Docker过程中创建的镜像.容器.网络.存储卷等. delete volu ...

  3. Hamburger

    Bread: 我觉得舒婷解决问题的思路还是很不错的,对于java 的窗口框架也是很熟悉,打码速度也快了很多. Meat:但是我发现你在命名的时候会出现随意的现象,如果命名只有你自己看得懂的话,那么会增 ...

  4. Daily Scrum - 11/17

    今天小组例会内容较少.拜重阳将一个简易的UI设计好push上TFS了,其他人没有太多进展.在原有项目基础上继续开发看似工作量变少,其实开始需要弄清楚原先代码的实现架构和各种借口还是比较困难的.

  5. ElasticSearch 2 (12) - Shard数调优(ElasticSearch性能)

    ElasticSearch 2 (12) - Shard数调优(ElasticSearch性能) 摘要 当创建一个索引的时候,我们经常会面对一个问题:要为索引分配多少个shard?多少个replica ...

  6. 使用Samba服务程序,让linux系统之间共享文件

    yum  install -y   cifs-utils mkdir  /database    创建挂载目录 在root家目录创建认证文件(依次为SMB用户名.SMB用户密码.SMB共享域)   v ...

  7. Alpha冲刺——测试随笔

    写在前面 作业链接 测试工作安排 测试模块 用户登录 日常管理模块 项目展示模块 测试计划 用户登录 测试功能 测试项 输入/操作 检验点 预期效果 用户登录 登录动作 点击登录 报错提示 无法登录, ...

  8. multer详解

    Express默认并不处理HTTP请求体中的数据,对于普通请求体(JSON.二进制.字符串)数据,可以使用body-parser中间件.而文件上传(multipart/form-data请求),可以基 ...

  9. shareSDK.js web版的使用

    自定义将要分享的内容 <!--MOB SHARE BEGIN--> <div class="-mob-share-open">分享</div> ...

  10. 服务端增加WCF服务全局异常处理机制

    服务端增加WCF服务全局异常处理机制,任一WCF服务或接口方式出现异常,将统一调用WCF_ExceptionHandler.ProvideFault方法,因此不需要每个方法使用try catch写法. ...