数学游戏

题目描述:

小T又发脑残了,没错,她又要求奇怪的东西,这次她想知道[X,Y]之间整数有多少可以表示成K个不同的B的幂的和形势。如\(x,y,k,b=15,20,2,2\),则有:

\[17=2^4+2^0
\]

\[18=2^4+2^1
\]

\[20=2^4+2^2
\]

共3个符合要求的数

输入格式:

输入仅包含一行4个空格隔开的整数X,Y,K,B(1≤X≤Y≤2^31 -1,1≤K≤20)

输出格式:

输出文件包含一行一个即为所求合法数字个数。

样例输入:

15 20 2 2

样例输出:

3

题解

首先想到的是dfs大力枚举所有子集,这样就拿到了78分的好成绩。

void dfs(int kk,int t,int now)
{
if(t==k)
{
if(now>=x&&now<=y) ans++;
return;
}
if(kk>y) return;
dfs(kk*b,t+1,now+kk);
dfs(kk*b,t,now);
}

紫书中介绍了几种枚举子集的方法,所以我用了二进制枚举法,即类似状压一样,1代表选,0代表不选,那我们就可以直接用一个for循环枚举两者之间的所有数,这就枚举了所有子集。

这让我想到了NOIP2006普及T4 数列

虽然没有剪枝,但似乎除T掉的点外其他都是0.00s过的。

这两个测试点的数据是这样的:

gema2.in:
1 2147483647 20 2
gema8.in:
4 2147483640 18 2

明显在卡子集生成。

代码如下:

#include <fstream>

using namespace std;

ifstream fin("maga.in");
ofstream fout("maga.out"); typedef long long LL; LL x, y, k, b; inline bool pan(LL a)//判断二进制下1是否有k个
{
int ans = 0;
while(a)
{
ans++;
a = a & (a-1);
if(ans > k)
return false;
}
return ans == k;
} inline LL getn(LL x)
{
LL ans = 0;
LL t = 1;
while(x > t)
{
t *= b;
ans++;
}
return 1 << ans;
} inline bool ppan(LL x)//判断是否越界
{
LL ans = 0;
LL tk = 1;
while(x)
{
if(x & 1)
ans += tk;
tk *= b;
x >>= 1;
}
return ans <= y;
} int main()
{
fin >> x >> y >> k >> b;
LL na = getn(x);
LL ans = 0;
for(LL i = na; ppan(i); ++i)
{
if(pan(i))
ans++;
}
fout << ans << '\n';
return 0;
}

其中pan函数比较玄学,看不懂的可以戳这里

正解其实思想与二进制枚举是差不多的,但复杂度大不相同。

dp[len][lim][gs]代表枚举到第len位,是否卡上限,其中一的个数有多少。

len为主线进行大力转移即可。

下面贴一下代码。

#include <fstream>

using namespace std;

ifstream fin("maga.in");
ofstream fout("maga.out"); int x, y, k, b; int dp[30][2][30];
int shu[10];//k进制下的每一位 inline int js(int len, bool lim, int gs)
{
if(!lim && dp[len][lim][gs])
return dp[len][lim][gs];
if(gs > k)
return 0;
if(!len)//如果长度到了就直接判掉
{
if(gs == k)
return dp[len][lim][gs] = 1;
else
return dp[len][lim][gs] = 0;
}
bool limit;
if(lim && !shu[len])//如果到上界且该位为0,那该位不能选1
limit = false;
else
limit = true;
int ans = 0;
for(int i = 0; i <= limit; ++i)
ans += js(len-1, lim && i == shu[len], gs+(i==1));
return dp[len][lim][gs] = ans;
} inline int get_ans(int x)
{
int tmp = 0;
while(x)//先转化为k进制下的数
{
shu[++tmp] = x % b;
x /= b;
}
return js(tmp, 1, 0);
} signed main()
{
fin >> x >> y >> k >> b;
fout << get_ans(y) - get_ans(x-1);
return 0;
}

当然,直接数位dp也是可以的。

inline int calc(int x){
if(x<=0)return 0;
memset(f,0,sizeof f);
memset(num,0,sizeof num);
size=0;
while(x){
num[++size]=x%b;
x/=b;
}
if(num[size]>1){
f[size][1][0]=1;
f[size][0][0]=1;
}else{
f[size][0][0]=1;
f[size][1][1]=1;
}
for(int i=size-1;i>=1;i--){
if(num[i]>=1){
for(int j=0;j<=min(k,size-i+1);j++){
if(j)f[i][j][0]+=f[i+1][j-1][0];
f[i][j][0]+=f[i+1][j][0];
f[i][j][0]+=f[i+1][j][1];
if(j){
if(num[i]==1){
f[i][j][1]+=f[i+1][j-1][1];
}else{
f[i][j][0]+=f[i+1][j-1][1];
}
}
}
}else{
for(int j=0;j<=min(k,size-i+1);j++){
f[i][j][0]+=f[i+1][j][0];
if(j)f[i][j][0]+=f[i+1][j-1][0];
f[i][j][1]+=f[i+1][j][1];
}
}
}
return f[1][k][0]+f[1][k][1];
}

20180606模拟赛T4——数学游戏的更多相关文章

  1. 20180606模拟赛T1——猫鼠游戏

    题目描述: 猫和老鼠在10*10的方格中运动,例如: *...*..... ......*... ...*...*.. .......... ...*.C.... *.....*... ...*... ...

  2. 20181228 模拟赛 T3 字符串游戏 strGame 博弈论 字符串

    3  字符串游戏(strGame.c/cpp/pas) 3.1  题目描述 pure 和 dirty 决定玩 T 局游戏.对于每一局游戏,有n个字符串,并且每一局游戏由K轮组成.具体规则如下:在每一轮 ...

  3. noip模拟赛 解谜游戏

    题目描述LYK进了一家古董店,它很想买其中的一幅画.但它带的钱不够买这幅画.幸运的是,老板正在研究一个问题,他表示如果LYK能帮他解出这个问题的话,就把这幅画送给它.老板有一个n*m的矩阵,他想找一个 ...

  4. 繁华模拟赛 Vicent与游戏

    #include<cstdio> #include<iostream> #include<algorithm> #include<cstring> #i ...

  5. 2017-9-10"切题如切菜杯"模拟赛T4 ZZI

    题目 YYH拿到了父亲给的钱欣喜若狂,把这些钱拿来造了n栋房子.现在他要给这些房子通电.他有两种方法:第一种是在房间里搭核电发电机发电,对于不同的房子,他需要花不同的代价Vi:,第二种是将有电的房子i ...

  6. 清北学堂模拟赛d6t5 侦探游戏

    分析:简化一下题意就是给任意两对点连一条权值为0的边,求出每次连边后最小生成树的权值和*2/(n - 1) * n. 每次求最小生成树肯定会爆炸,其实每次加边只是会对最小生成树上的一条边有影响,也就是 ...

  7. 20180610模拟赛T4——木棍

    有\(N\)根木棍,每根的长度\(L\)和重量\(W\)已知.这些木棍将被一台机器一根一根地加工.机器需要一些启动时间来做准备工作,启动时间与木棍被加工的具体情况有关.启动时间遵循以下规则: 加工第一 ...

  8. 20180523模拟赛T4——Number

    [题目描述] 最近

  9. 【20170521校内模拟赛】热爱生活的小Z

    学长FallDream所出的模拟赛,个人感觉题目难度还是比较适中的,难度在提高+左右,可能比较接近弱省省选,总体来讲试题考查范围较广,个人认为还是很不错的. 所有试题如无特殊声明,开启-O2优化,时限 ...

随机推荐

  1. [LeetCode] 377. Combination Sum IV 组合之和之四

    Given an integer array with all positive numbers and no duplicates, find the number of possible comb ...

  2. 黑苹果MacOS安装记录

    https://blog.daliansky.net/macOS-Catalina-10.15-19A583-Release-version-with-Clover-5093-original-ima ...

  3. zlib: 不同语言,比如go, php, python 压缩的结果可能不同

    1.这个是实际工作中发现的问题,一边用了go语言对一个文件进行了zlib压缩,然后我用 php 写了个脚本对同一个文件进行zlib压缩,但是生成的两个文件不同,当时一直以为是压缩参数选择错了,后来经过 ...

  4. Tomcat启用HTTPS协议配置过程

    Article1较为简洁,Article2较为详细,测试可行. Article1 概念简介 Tomcat 服务器是一个免费的开放源代码的Web 应用服务器,属于轻量级应用服务器,在中小型系统和并发访问 ...

  5. jenkins+sonarqube进行代码质量检测

    JavaNeverGiveUp教程篇 用jenkins+sonarqube去检查代码是非常方便的,它能检查出代码中可能存在的一些问题,比如io流未关闭.空指针异常.死循环.代码不规范等问题. 1. 搭 ...

  6. 获取豆瓣电影数据(R与API获取网页数据)

    一般成熟的网站都会有反爬虫策略,例如限制访问次数,限制访问 IP,动态显示数据等.爬虫和反爬虫就是一直相爱相杀地互相钳制.如果要通过爬虫来获取某些大型网站的数据,那是一件很费时费力的活.小白总遭遇过在 ...

  7. 算法设计与分析(李春保)练习题答案v2

    ----------------------------------------------------- Page 1 --------------------------------------- ...

  8. Prometheus 监控Mysql服务器及Grafana可视化

    Prometheus 监控Mysql服务器及Grafana可视化. mysql_exporter:用于收集MySQL性能信息. 使用版本 mysqld_exporter 0.11.0 官方地址 使用文 ...

  9. RAID(独立磁盘冗余阵列)简介

    RAID(独立磁盘冗余阵列) 在大数据技术出现之前,人们就需要面对这些关于存储的问题,对应的解决方案就是RAID技术. RAID(独立磁盘冗余阵列)技术主要是为了改善磁盘的存储容量,读写速度,增强磁盘 ...

  10. 基于 Ubuntu 系统安装 CUDA 和 cuDNN

    ************************************************ 显卡:GTX 1050Ti 系统:Ubuntu 18.0.4 安装的CUDA:10.0 版本 **** ...