ural1057 Amount of Degrees数位统计入门题
来源:互联网 发布:vb6 连接mysql数据库 编辑:程序博客网 时间:2024/05/29 03:23
题目大意:给你一个区间,由[m,n]表示,然后给你一个k,一个b,分别代表在这个区间内的数字的b进制数内含有k个1的数字有几个。
很明显,此题满足区间减法,就是[m,n]的值就等于[0,m]的值减去[0,n-1]的值,注意是n-1,我因为这个WA了一发,还找了半个小时的错,很奇怪,这个写错了之后数据也不好找,提供一组数据:13974 28320 8 2,answer应该是3148
在知道有数位统计这个东西之前,我是想用组合数学做的,大体思想就是统计出大数的最高位与小数的最高位之间有几位,然后填坑法求解,只是有个想法,并没有把代码写出来。后来上了数位统计的集训课,就试着用这道题联系一下,其实思路很简单,用一个数组f[i][j]来记录前i位二进制数中含有j个1的有几个,这里有一个递推公式:f[i][j] = f[i-1][j] + f[i-1][j-1],原因很简单,对于第i位,要么为1,要么为0,如果是1,就是f[i-1][j-1],如果是0,就是f[i-1][j]。初始设f[0][0]为1,dp出来就好了
本题解法,就是计算出来从0到n的二进制数含有k个1的有几个,注意最后要讨论这个数本身是不是,此处用到的算法:x&(1<<i),判断x第i位是不是1;x^(1<<i),让x等于x去掉最高位的1的数。
最后对于非二进制,只要找到b进制第一个大于1的位置,然后从这个位置往后全部置为1就好了,因为题目要求就是找有几个1,大于1的话就是说明这个数比后面全是1的数大,就可以直接用后面全是1的数代替。
AC代码:
<span style="font-family:KaiTi_GB2312;font-size:18px;">#include <cstdio>#include <cstring>#include <algorithm>#include <iostream>using namespace std;int f[35][35];int a[35];void init(){ memset(f,0,sizeof(f)); f[0][0] = 1; for(int i = 1; i <= 31; i++) { f[i][0] = f[i-1][0]; for(int j = 1; j <= i; j++) { f[i][j] = f[i-1][j] + f[i-1][j-1]; } }}int count(int x, int k){ int tot = 0; int ans = 0; for(int i = 31; i > 0; i--) { if(x&(1<<i)) { tot++; if(tot > k) break; x = x^(1<<i); } if((1 << (i - 1)) <= x) ans+=f[i-1][k-tot]; } if(tot + x == k) ++ans; //此时x == 0,答案加上x return ans;}int main(){ //freopen("in.txt","r",stdin); init(); int m,n,k,b; while(scanf("%d%d%d%d",&m,&n,&k,&b)!=EOF) { //cout<<count(13974,8)<<endl<<count(28320, 8); if(b == 2) //此处写麻烦了,可以整个都用数组存起来的,不用再转化成数字,这样的话函数内部也得改 printf("%d\n",count(n,k) - count(m-1,k)); else { int mm,nn; mm = nn =0; int tem = 0; while(m){ a[tem++] = m % b; m /= b; } int cn = 1; for(int i = tem - 1; i >= 0; i--) { if(a[i] > 1) { for(int j = i; j >= 0; j--) a[j] = 1; break; } } for(int i = 0; i < tem; i++) { mm+=a[i]*cn; cn*=2; } tem = 0; while(n) { a[tem++] = n %b; n /= b; } cn = 1; for(int i = tem - 1; i >= 0; i--) { if(a[i] > 1) { for(int j = i; j >= 0; j--) a[j] = 1; break; } } for(int i = 0; i < tem; i++) { nn+=a[i]*cn; cn*=2; } printf("%d\n",count(nn,k) - count(mm-1,k)); } }}</span>
- ural1057 Amount of Degrees数位统计入门题
- [ural1057]Amount of Degrees && 数位DP
- URAL1057 Amount of Degrees 数位DP
- ural1057 Amount of Degrees 数位dp
- ural1057. Amount of Degrees
- ural1057 Amount of Degrees 【数位dp】论文例题
- Ural 1057(Amount of Degrees-数位统计入门)
- URAL 1057 Amount of Degrees (数位统计)
- Ural 1057. Amount of Degrees 数位统计
- ural 1057 - Amount of Degrees(数位统计)
- ural 1057 Amount of Degrees(数位统计)
- [ACM] ural 1057 Amount of degrees (数位统计)
- URAL 1057 Amount of Degrees(数位统计)
- ural 1057 Amount of degrees 数位DP (入门)
- URAL 1057 - Amount of Degrees (入门数位DP)
- [数位dp] ural 1057 Amount of Degrees
- ural 1057 Amount of Degrees(数位DP)
- ural 1057 Amount of degrees 【数位dp】
- Shell脚本学习笔记
- Android入门第十六篇之Style与Theme
- Hdu oj 1875 畅通工程再续
- ZOJ1157, POJ1087,UVA 753 A Plug for UNIX (最大流)
- UI_Target-Action
- ural1057 Amount of Degrees数位统计入门题
- Esfog_UnityShader教程_UnityShader语法实例浅析
- Websphere为datasource设置resultSetHoldability
- 照片墙设计与制作
- java连接MySQL数据库
- 安卓开发中的折线图
- Dark roads--hdoj
- 数据结构(Java语言)——Stack简单实现
- Fractions Again?!