2^k进制数问题(动态规划+高精度/C++)
来源:互联网 发布:北大网络教育 编辑:程序博客网 时间:2024/05/10 01:10
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≤30000)是事先给定的。
问:满足上述条件的不同的r共有多少个?
输入格式
输入文件只有1行,为两个正整数,用一个空格隔开:
k W
输出格式
输出文件为1行,是一个正整数,为所求的计算结果,即满足条件的不同的r的个数(用十进制数表示),要求最高位不得为0,各数字之间不得插入数字以外的其他字符(例如空格、换行符、逗号等)。(提示:作为结果的正整数可能很大,但不会超过200位)
样例输入
3 7
样例输出
36
设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共有多少个?
输入格式
输入文件只有1行,为两个正整数,用一个空格隔开:
k W
输出格式
输出文件为1行,是一个正整数,为所求的计算结果,即满足条件的不同的r的个数(用十进制数表示),要求最高位不得为0,各数字之间不得插入数字以外的其他字符(例如空格、换行符、逗号等)。(提示:作为结果的正整数可能很大,但不会超过200位)
样例输入
3 7
样例输出
36
2^k进制数转换为2进制数时,每一位各对应2进制数中的k位
如8(2^3)进制数234做转换时:
0—000 1—001
2—010 3—011
4—100 5—101
6—110 7—111
(234)8 =(101011)2
因此在处理时把w按每k位算2^k进制中的一位。
以题目的例子为例,长度为7位的01字串按3位一段就这样分:0/000/000。其中除了首段,每段都小于(111)2,也即小于2k,而首段自然是小于2w%k(对于w%k为0时也成立)了。
如果首段为0,则当这个2k进制数位数分别为2、3、…、[n/k]时,如果用bm表示2k,对应的解的个数分别为C[bm-1][2]、C[bm-1][3]、…、C[bm-1][n/k](C[i][j]表示从i个数里选j个构成一组组合有多少种情况)。
如果首段不为0,设首段为x,则后面n/k位必定都有值,则解就有c[bm-x-1][n/k]个。
求组合数可以用这个公式:
C[n][m]=C[n-1][0]+C[n-1][1]+C[n-1][2]+......+C[n-1][m-1]
因为C[n][m-1]=C[n-1][0]+C[n-1][2]+C[n-1][2]+......+C[n-1][j-2]
所以可化简为C[n][m]=C[n-1][m-1]+C[n-1][m]
由于题目数据位数很多,因此用高精度加法。代码如下
如8(2^3)进制数234做转换时:
0—000 1—001
2—010 3—011
4—100 5—101
6—110 7—111
(234)8 =(101011)2
因此在处理时把w按每k位算2^k进制中的一位。
以题目的例子为例,长度为7位的01字串按3位一段就这样分:0/000/000。其中除了首段,每段都小于(111)2,也即小于2k,而首段自然是小于2w%k(对于w%k为0时也成立)了。
如果首段为0,则当这个2k进制数位数分别为2、3、…、[n/k]时,如果用bm表示2k,对应的解的个数分别为C[bm-1][2]、C[bm-1][3]、…、C[bm-1][n/k](C[i][j]表示从i个数里选j个构成一组组合有多少种情况)。
如果首段不为0,设首段为x,则后面n/k位必定都有值,则解就有c[bm-x-1][n/k]个。
求组合数可以用这个公式:
C[n][m]=C[n-1][0]+C[n-1][1]+C[n-1][2]+......+C[n-1][m-1]
因为C[n][m-1]=C[n-1][0]+C[n-1][2]+C[n-1][2]+......+C[n-1][j-2]
所以可化简为C[n][m]=C[n-1][m-1]+C[n-1][m]
由于题目数据位数很多,因此用高精度加法。代码如下
#include<iostream>#include <cstdio>#include <cstring>using namespace std;int k,n,bx,hx,ans[201];int c[512][512][200];//第三维为高精度 void plus1(int x[],int y[],int z[]) { z[0]=max(x[0],y[0]); for(int i=1;i<=z[0];i++) { z[i]+=x[i]+y[i]; z[i+1]+=z[i]/10; z[i]%=10; } if(z[z[0]+1]!=0)z[0]++;}//高精度加法1(z=x+y) void plus2(int x[],int y[]) { x[0]=max(x[0],y[0]); for(int i=1;i<=x[0];i++) { x[i]+=y[i]; x[i+1]+=x[i]/10; x[i]%=10; } if(x[x[0]+1]!=0)x[0]++;}//(x+=y)int main(){ cin>>k>>n; bx=1<<k;//2^k hx=1<<(n%k); for(int i=0;i<=bx;i++) { for(int j=0;j<=i;j++) { if(j==0) c[i][j][0]=c[i][j][1]=1;//c[i][j][0]为位数 else plus1(c[i-1][j],c[i-1][j-1],c[i][j]);//求组合数 } } for(int i=2;i<=n/k&&i<bx;i++)plus2(ans,c[bx-1][i]);//首位为0的情况 for(int i=1;i<hx&&n/k+i<bx;i++)plus2(ans,c[bx-i-1][n/k]);//首位不为0的情况 for(int i=ans[0];i>=1;i--)cout<<ans[i]; cout<<endl; return 0;}
0 0
- 2^k进制数问题(动态规划+高精度/C++)
- “k车问题”&动态规划
- 【动态规划】最大k乘积问题
- Vijos P1354 Hanoi双塔问题(动态规划,高精度)
- URAL 1009|URAL 1012|URAL 1013|K-based Numbers|高精度|动态规划
- HDU1502 动态规划计数 高精度
- 过河卒-动态规划+高精度
- HDU1502_Regular Words动态规划+高精度
- 动态规划问题2
- 动态规划问题2
- 动态规划 problem K
- 动态规划K
- 高精度数学-洛谷P1066 2^k进制数
- [noip2006]2^k进制数(高精度+进制)
- ☆逆序对 动态规划+高精度
- 10069 - Distinct Subsequences(高精度+动态规划)
- [动态规划+高精度] 矩阵取数游戏
- 串的计数--动态规划和高精度
- 软件工程好书
- 1141 走迷宫
- Android实战简易教程-第三十一枪(基于加速度传感器的摇一摇功能实例)
- hdu5328(不用dp)
- HDU 2094 产生冠军 (STL:set用法)
- 2^k进制数问题(动态规划+高精度/C++)
- hdoj 1969 Pie
- leetcode 65: Valid Number
- JAVA开发_File
- 为什么你宁愿每周工作90小时,也不做任何改变?
- gem install 时报错,no such file to load -- zlib
- 知识管理资源
- 线程同步---信号量(无名)
- C# MVC3获取渲染后视图的HTML