题面

传送门:https://www.luogu.org/problemnew/show/P1066


Solution

这是一道神奇的题目,我们有两种方法来处理这个问题,一种是DP,一种是组合数。

这题需要高精度,以下省略此声明

.

如果你对数学不感兴趣/喜欢写DP/(不想虐待自己),这里是DP做法。

首先,我们可以发现,这个数最多有w/k位(向上取整),如下图所示:

那么,我们就可以以这个特性做DP啦。

设f[i][j]表示枚举到第i位(指2^k进制下的),最后一位数为j。

f[i][j] = ∑ f[i-1][k] ((j==0 and k==0) or k<j) 

这里的k显然是可以用前缀和优化的

初始化 f[1][i]=1 (i=0~2^(w%k)-1)

当然,还有一些小细节:f[倒数第2/第1个][0]=0

答案为∑f[w/k][i] 

(因为我没写过DP做法,这个做法纯口胡,如有错误请通知蒟蒻博主)


那....组合数呢?

事实上,这题的组合数做法的确很妙,(当然也有不少细节)

假设我们枚举了第一位数,那么后面位数的方案数是可以通过组合数来计算出来的。

因为后面的数要比第一位大,那么后面的数相当于从 [第一位数+1,2^k-1] 这个数的区间中选出x个数(x为后面的位数数量)来 (因为每一种方案都可以通过摆成升序满足题目要求)。

但是考虑到有可能有若干个前导零,我们还要枚举第一个位数从哪开始。

因为枚举了前导零,我们枚举第一位数时应该从1开始(从0开始会有重复)

这样子,答案为:

(事实上口胡起来简单,写起来还有很多细节,这得亲自体会然后就会感到这题的毒瘤)

就酱,我们就可以切掉嘴巴AC出这道题啦(~ ̄▽ ̄)~


Code

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
struct Int128
{
static const int N=500;
int a[N],len;
Int128()
{
memset(a,0,sizeof a);
len=0;
}
void Print()
{
for(int i=len;i>=1;i--)
printf("%d",a[i]);
}
friend Int128 operator * (Int128 A,int B)
{
for(int i=1;i<=A.len;i++)
A.a[i]*=B;
bool IsFullZero=true;
for(int i=1;i<=A.len;i++)
{
if(A.a[i]>=10)
{
A.a[i+1]+=A.a[i]/10,A.a[i]%=10;
if(i==A.len and A.a[i+1]!=0)
A.len++;
}
if(A.a[i]!=0) IsFullZero=false;
}
if(IsFullZero==true) A.len=1;
return A;
}
friend Int128 operator / (Int128 A,int B)
{
Int128 ans;
int temp=0;
for(int i=A.len;i>=1;i--)
{
temp=temp*10+A.a[i];
if(temp>=B)
{
ans.a[i]=temp/B,temp=temp%B;
ans.len=max(ans.len,i);
}
}
return ans;
}
friend Int128 operator + (Int128 A,Int128 B)
{
if(A.len<B.len) swap(A,B);
for(int i=1;i<=A.len;i++)
{
A.a[i]=A.a[i]+B.a[i];
if(A.a[i]>9)
{
A.a[i+1]++;A.a[i]-=10;
if(i==A.len)
A.len++;
}
}
return A;
}
};
const int N=1<<(9+1);
Int128 C[N];
int n,x,K,w,first,m;
int main()
{
scanf("%d%d",&K,&w); first=1<<(w%K),x=w/K;
if(w%K==0)
first=1<<K,x--;
m=1<<K; Int128 ans;
for(int j=0;j<=x-1;j++)
{
int tx=x-j;
memset(C[tx].a,0,sizeof C[tx].a);
C[tx].a[1]=1,C[tx].len=1;
for(int i=tx+1;i<=m;i++)
{
memset(C[i].a,0,sizeof C[i].a);
C[i]=(C[i-1]*i)/(i-tx);
}
if(j!=0) first=m;
for(int i=1;i<m and i<first;i++)
{
if(m-1-i<tx) break;
ans=ans+C[m-1-i];
}
//ans.Print();
//cerr<<endl;
} ans.Print();
return 0;
}

[Luogu P1066] 2^k进制数 (组合数或DP)的更多相关文章

  1. [luogu]P1066 2^k进制数[数学][递推][高精度]

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

  2. Luogu P1066 2^k进制数 组合数学

    分两种情况:$k|n$和$k$不整除$n$ 如果$k|n$,那么长度为$n$的二进制数就能被恰好分成$n/k$个块:所以若某个数长度是$x$个块,由于每个块内能填不同的$2^k-1$个数,那么就有$C ...

  3. 洛谷P1066 2^k进制数

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

  4. 洛谷 P1066 2^k进制数

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

  5. 洛谷P1066 2^k进制数(题解)(递推版)

    https://www.luogu.org/problemnew/show/P1066(题目传送) (题解)https://www.luogu.org/problemnew/solution/P106 ...

  6. [NOIP2006] 提高组 洛谷P1066 2^k进制数

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

  7. P1066 2^k进制数

    传送门 题目描述 设r是个2^k 进制数,并满足以下条件: (1)r至少是个2位的2^k 进制数. (2)作为2^k 进制数,除最后一位外,r的每一位严格小于它右边相邻的那一位. (3)将r转换为2进 ...

  8. 【洛谷p1066】2^k进制数

    (不会敲键盘惹qwq) 2^k进制数[传送门] 算法标签: (又是一个提高+省选-的题) 如果我说我没听懂你信吗 代码qwq: #include<iostream> #include< ...

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

    1649:[例 2]2^k 进制数 时间限制: 1000 ms         内存限制: 524288 KB [题目描述] 原题来自:NOIP 2006 提高组 设 r 是个 2k 进制数,并满足以 ...

随机推荐

  1. 随机梯度下降法(Stochastic gradient descent, SGD)

    BGD(Batch gradient descent)批量梯度下降法:每次迭代使用所有的样本(样本量小)    Mold 一直在更新 SGD(Stochastic gradientdescent)随机 ...

  2. JAVA对象转换为JSON及日期格式转换处理

    1.JSON日期格式转换 默认JSON对DATE类型会转换成一个多属性对象, 而不是单独的一个字符串, 在某些应用处理上不是很方便,  可以利用JsonValueProcessor来实现日期的转换. ...

  3. Java知识系统回顾整理01基础03变量05变量命名规则

    一.命名规则 变量命名只能使用字母 .数字. $. _ 变量第一个字符 只能使用: 字母. $. _ 变量第一个字符 不能使用数字 注:_ 是下划线,不是-减号或者-- 破折号 int a= 5; i ...

  4. ElasticSearch 索引 VS MySQL 索引

    前言 这段时间在维护产品的搜索功能,每次在管理台看到 elasticsearch 这么高效的查询效率我都很好奇他是如何做到的. 这甚至比在我本地使用 MySQL 通过主键的查询速度还快. 为此我搜索了 ...

  5. Python 疑难问题:[] 与 list() 哪个快?为什么快?快多少呢?

    本文出自"Python为什么"系列,请查看全部文章 在日常使用 Python 时,我们经常需要创建一个列表,相信大家都很熟练了吧? # 方法一:使用成对的方括号语法 list_a ...

  6. 多测师讲解selenium_输入性弹框定位_高级讲师肖sir

    #输入性弹框from selenium import webdriverfrom time import sleepdrvier=webdriver.Chrome()url='file:///F:\d ...

  7. vbox挂载共享文件夹

      版权 挂载共享文件夹很简单,有2种方法,1是自动挂载,2是手动挂载. 一.自动挂载步骤: 1,把想共享的文件夹设置为共享. 2,在virtualbox界面对虚拟机设置共享文件夹,如下图.

  8. golang xpath解析网页

    https://github.com/antchfx/htmlquery package main import ( "fmt" "github.com/antchfx/ ...

  9. centos8平台使用vmstat监控系统

    一,vmstat的用途和特点: vmstat 是一个常用的系统性能分析工具,主要用来分析系统的内存使用情况,也常用来分析 CPU 上下文切换和中断的次数. 相对于 iostat 来说,vmstat 可 ...

  10. php-ffmpeg 操作视频/音频文件

    php-ffmpeg 是一个php操作视频/音频文件的类库. GitHub地址:https://github.com/PHP-FFMpeg/PHP-FFMpeg/ 使用composer快速安装:com ...