CF261E Maxim and Calculator

题目大意:

有两个初始参数 $ a=1 $ , $ b=0 $ ,你可以对它们进行两个操作: $ b~+=1 $ 或 $ a~\times =b $ ,最终的 $ a $ 才是你所得到的数 。 现在给你三个数 $ l,r,p $ ,让你求在区间 $ [l,r] $ 内可以用不超过 $ p $ 次操作得到的数的个数。数据范围: $ (2<=l<=r<=10^{9},1<=p<=100) $



$ solution: $

很神仙的一道题,当时看了很久只能想到:每个我所得到的数,一定是若干个可能不同的 $ b $ 的乘积,。又因为 $ b $ 每次只能加1,所以我们如果要用最少的步数得到一个数 $ a $ ,最终 $ b $ 的大小一定是 $ b $ 的最大质因子!同理,最大质因子大于 $ p $ 的数一定不可通过少于 $ p $ 的次数得到

当时的想法是线性筛最大质因子,然后暴力判断,复杂度 $ O(n) $ 显然超时。然后死活没想到可以筛 $ p $ 以下质数所构成的数( $ 10^9 $ 里面不超过 $ 3\times 10^6 $ 个 )!

好吧,回归正题。根据上面我们的分析,所有最大质因子大于 $ p $ 的数一定不可通过少于 $ p $ 的次数得到,所以我们可以找出所有最大质因子在 $ p $ 以内的数。怎么求?这其实等同于求 $ p $ 以内的所有质数可以构造的数(注意题目说 $ 2\leq r $ ,所以不考虑1)(然后我们现线性筛质数,再搜索一下即可)。然后我们发现这样的数不超过 $ 3\times 10^6 $ 个,我们用一个数组 $ a[] $ 存起来。于是我们考虑怎么判断 $ a[] $ 里面的数是否能在 $ p $ 次操作内得到。

首先我们要明白一个点:所有 $ a[] $ 里的数都可以通过 $ a[] $ 里比它小的数构造出来。证明:对于 $ a[] $ 里的数 $ i $ ,如果它的最大质因子为 $ k $ ,那么 $ i/k $ 一定在 $ a[] $ 中,因为 $ i/k $ 的所有质因子都小于 $ p $ 。于是我们考虑 $ f[i][j] $ 表示 $ b $ 的大小为 $ i $ 时 $ j $ 的最小构造步数。我们从小到达枚举 $ b $ ,每个 $ b $ 可以选用很多次,这不就是一个完全背包吗?不过是 $ b $ 要被乘上去而已!注意我们的 $ a[] $ 数组是离散化的,我们先排一遍序,然后用单调队列找到 $ a[k]=a[j]*i $ 即可做到 $ O(1) $ 转移!

$ f[i][k]=f[i][j]+1 \quad (~a[j]\times i=a[k]~) $

复杂度: $ O(p\times 3 \times 10^6) $ ,很勉强



$ code: $

#include<iostream>
#include<cstdio>
#include<iomanip>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<ctime>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set> #define ll long long
#define db double
#define rg register int using namespace std; int l,r,p,n; // n表示a数组的大小
int ans,tt; // tt素数个数
int a[3000005]; //最大质因子小于p的数的集合
int f[3000005]; //构造a[i]这个数的最少步数
bool d[3000005]; //是否已经加入贡献
int pr[505]; //素数表
bool vis[505]; //筛素数 inline int qr(){
register char ch; register bool sign=0; rg res=0;
while(!isdigit(ch=getchar()))if(ch=='-')sign=1;
while(isdigit(ch))res=res*10+(ch^48),ch=getchar();
if(sign)return -res; else return res;
} inline void prime(int x){ //线性筛素数
for(rg i=2;i<=x;++i){
if(!vis[i])pr[++tt]=i;
for(rg j=1;j<=tt;++j){
if(i*pr[j]>x)break;
vis[i*pr[j]]=1;
if(!(i%pr[j]))break;
}
}
} //找到最大质因子小于p的数
//等效于我们构造小于p的质数所能构造的数
inline void dfs(int i,ll v){ //i是当前轮到的质数
if(i>tt)return ;
dfs(i+1,v); //不用这个质数
while(1){
v*=pr[i]; //不断选用这个质数
if(v>r)return ; //退出
dfs(i+1,v);
a[++n]=v; //记录这个数
}
} int main(){
l=qr(); r=qr(); p=qr();
prime(p); dfs(1,1); a[++n]=1; //预处理
sort(a+1,a+n+1); f[1]=0;
for(rg i=2;i<=n;++i) f[i]=101; //赋初值无穷大
for(rg i=2;i<=p;++i){
for(rg j=1,k=1;j<=n;++j){
while(k<=n&&a[j]*i>a[k])++k; //因为a数组离散化,所以单调队列查找
if(k>n)break; if(a[j]*i!=a[k])continue;
f[k]=min(f[k],f[j]+1); //更新步数
if(d[k]||f[k]+i>p||a[k]<l)continue; //注意第二个判断
d[k]=1; ++ans; //步数在p范围内,计入答案
}
}
printf("%d\n",ans);
return 0;
}

CF261E Maxim and Calculator (质数,完全背包)的更多相关文章

  1. CF261E Maxim and Calculator

    CF261E Maxim and Calculator 洛谷评测传送门 题目描述 Maxim has got a calculator. The calculator has two integer ...

  2. [CF261E]Maxim and Calculator_搜索_欧拉筛素数_动态规划

    Maxim and Calculator 题目链接:https://www.luogu.org/problem/CF261E 数据范围:略. 题解: 考试的时候只会暴力,学弟太强了$\%\%\% Or ...

  3. Codeforce 水题报告

    最近做了好多CF的题的说,很多cf的题都很有启发性觉得很有必要总结一下,再加上上次写题解因为太简单被老师骂了,所以这次决定总结一下,也发表一下停课一星期的感想= = Codeforces 261E M ...

  4. 考前停课集训 Day2 非

    因为太长了 所以一天一天分开发 Day2 昨天晚上没开黑车 没脱衣服就睡了 可能是我难受了…… 新的一天. 早上好. 我没去晨跑,早上先和团长集合了,没看见rkbudlo来 于是就先吃饭了 去机房的时 ...

  5. HGOI 20190519 题解

    脑补了一下今天的比赛难度和之前zju-lzw出的题目画风迥异. 难度完全不是一个水平的好伐. Probem A palindrome 给出一个$n$个元素的数组,可以任意指定一个数字$m$让所有$a_ ...

  6. Codeforces 922 思维贪心 变种背包DP 质因数质数结论

    A #include <bits/stdc++.h> #define PI acos(-1.0) #define mem(a,b) memset((a),b,sizeof(a)) #def ...

  7. BZOJ 1004: [HNOI2008]Cards( 置换群 + burnside引理 + 背包dp + 乘法逆元 )

    题意保证了是一个置换群. 根据burnside引理, 答案为Σc(f) / (M+1). c(f)表示置换f的不动点数, 而题目限制了颜色的数量, 所以还得满足题目, 用背包dp来计算.dp(x,i, ...

  8. BZOJ 1025: [SCOI2009]游戏( 背包dp )

    显然题目要求长度为n的置换中各个循环长度的lcm有多少种情况. 判断一个数m是否是满足题意的lcm. m = ∏ piai, 当∑piai ≤ n时是满足题意的. 最简单我们令循环长度分别为piai, ...

  9. hdu 6125 -- Free from square(状态压缩+分组背包)

    题目链接 Problem Description There is a set including all positive integers that are not more then n. Ha ...

随机推荐

  1. 机器学习中L1,L2正则化项

    搞过机器学习的同学都知道,L1正则就是绝对值的方式,而L2正则是平方和的形式.L1能产生稀疏的特征,这对大规模的机器学习灰常灰常重要.但是L1的求解过程,实在是太过蛋疼.所以即使L1能产生稀疏特征,不 ...

  2. python对象的引用

    1 利用 * 星号生成二维及二维以上的list时,特别要注意有的量引用是相同的.如果后面要给list赋值,最好不要这样生成list. 可以先这样生成,再打印输出后,粘贴到程序中重新赋值. a = [[ ...

  3. pyinstaller如何将自己写的模块一并打包到exe中

    使用pyinstaller命令 pyinstaller -F main.py 打包时,若mian.py代码中存在引入自己写的模块,而打包成exe文件时,并不会自动引入自己写的模块,打包成功后,点击打开 ...

  4. postman杂记

    接到测试任务,测试6个接口 rap2 上的接口比较多,整体导出内容太多 就一个接口一个接口的,复制到了postman上 rap2部分接口,开发没有备注简介内容:通知开发备注下 对接口的理解,还是靠功能 ...

  5. Spring对Jdbc的封装——JdbcTemplate的使用

    链接:https://pan.baidu.com/s/15luDElW4oeEaP0nvEQ_40w 提取码:i2r1 JdbcTemplate是Spring对JDBC的封装,目的是使JDBC更加易于 ...

  6. jenkins shell 取当前时间

    now=`date +%Y%m%d%H%M%S` echo $now newfilename=abc_${now}.warfor i in `ls *.jmx`:dojmeter -n -t $i r ...

  7. [Vim] 01 凡人操作

    历史评价 编辑器之神 一个凡人的自我修养 成神是不可能成神的,只能是先入个门,然后一点一点学 Vim 官网 三种模式 插入模式(注意看光标) 命令模式(注意看光标) 编辑模式(注意看光标) 其实还有一 ...

  8. mysql数据库问题———登录进去无法操作显示You must reset your password using ALTER USER statement before executing this statement

    linux操作mysql数据库,可以登陆进去,但是操作所有命令都显示You must reset your password using ALTER USER statement before exe ...

  9. [Bzoj1911][Apio2010]特别行动队(斜率优化)

    题目链接 斜率优化的经典模型,将序列分成若干段,每段有一个权值计算方法,求权值和最大/小 暴力的dp $O(n^{2})$ dp[i]为1-i的序列的最优解.sum[i]为前缀和,$D(i)=ax^{ ...

  10. [BZOJ 3123] [SDOI 2013]森林(可持久化线段树+并查集+启发式合并)

    [BZOJ 3123] [SDOI 2013]森林(可持久化线段树+启发式合并) 题面 给出一个n个节点m条边的森林,每个节点都有一个权值.有两种操作: Q x y k查询点x到点y路径上所有的权值中 ...