【题解】Kathy函数 [BZOJ1223] [P2235] [HNOI2002]
【题解】Kathy函数 [BZOJ1223] [P2235] [HNOI2002]
这几疯狂刷了数位\(dp\)的题,到这道题时被卡了一天,一看大佬的讲解发现居然是求回文数╮(╯_╰)╭
感觉被大佬狠狠地蹂蹑了一番。。。
废话到此结束,进入正题:
满足\(f(n)=n\)的\(n\)在二进制的形式下一定是一个回文数
例如:
\(f(1)=1\) (\(1\))
\(f(3)=3\) (\(11\))
\(f(5)=5\) (\(101\))
\(f(7)=7\) (\(111\))
至于为什么会有这个性质,这里就作证明(都懒得给自己的懒惰找借口了)
假设已经成功的证明了这个结论,那么问题就变成了在\([1,n]\)中找到符合二进制形式为回文数的总个数,这里我提供一种用\(dfs\)实现数位\(dp\)的思路
可以先写一下这道题(因为不需要高精):
只需要输出区间内回文数的总个数
LightOJ1205
用\(dfs\)找回文数个数:
一:转进制
首先我们需要把\(n\)转化为二进制存储在一个数组\(num[lenn]\)中
二:DFS
\(dfs(st,pos,ok,limit)\)
记搜以及状态表示:
用一个数组记录已经搜过的地方,\(dp[pos][ok][st]\) 示已经选到了第\(pos\)位,前已经选好的是否满足回文\(ok\),去前导\(0\)后共有\(st\)位,并且前面已选的并未全部达到上限(\(pos\)开始后面可以随意选\(0\)或\(1\)),此时的回文数总数。
\(limit\)表示前面已选的是否全达到上限,如果是,那么这一位的可以选的数的上限为\(num[pos]\),否则可以随意选,\(ed=limit?num[pos]:1\)。
如果当前状态并未受限,且当前状态的\(dp\)值已经被记录,直接返回这个值
如何枚举递归
每当选了一个数\(i\)时, \(tmp[pos]=i\)。
(1) 如果前面都没选(即全是前\(0\),\(st=pos\)),
\(ans+=dfs\)(\(st-1\),\(pos-1\),\(ok\),\(limit\)&&\(i==ed\))
(2) 如果前面选了(即\(st>pos\))
- 如果当前状态是回文数,且当前选的这位在\(st\)的后半段(即\(ok\)&&\(pos<=st/2\)),则\(okk=tmp[st-pos+1]==i\)
- 否则 \(okk=ok\)。
\(ans+=dfs\)(\(st\),\(pos-1\),\(okk\),\(limit\)&&\(i==ed\))
\(dfs\)边界
当\(pos==0\)(即已经选完了所有位)
如果满足回文数(即\(ok=1\))且选了数(即并非全是\(0\),\(st>0\))\(return 1\)。
三.高精
推荐写结构体,用起来方便,不会的可以参考一下大佬的高精模板
最后附上代码:
#include<cstdio>
#include<cstring>
using namespace std;
typedef long long ll;
const int base = 1e8;
const int N = 20;
int aux[N << 3];
struct bigint {
int s[N], l;
void CL() { l = 0; memset(s, 0, sizeof(s)); }
void pr()
{
printf("%d", s[l]);
for (int i = l - 1; i; i--)
printf("%08d", s[i]);
}
void re_l()
{
int i, x = 0, k = 1, L = 0, fl, o;
char c = getchar();
for (; c < '0' || c > '9'; c = getchar());
for (; c >= '0' && c <= '9'; c = getchar())
{
if (!(L - 1) && !aux[L])
L--;
aux[++L] = c - '0';
}
CL();
l = L / 8 + ((o = L % 8) > 0);
for (i = 1; i <= o; i++)
x = x * 10 + aux[i];
if (o)
s[l] = x;
fl = !o ? l + 1 : l;
for (i = o + 1, x = 0; i <= L; i++, k++)
{
x = x * 10 + aux[i];
if (!(k ^ 8))
{
s[--fl] = x;
x = k = 0;
}
}
if (!l)
l = 1;
}
ll toint()
{
ll x = 0;
for (int i = l; i; i--)
x = x * base + s[i];
return x;
}
bigint operator = (int b)
{
CL();
do
{
s[++l] = b % base;
b /= base;
} while (b > 0);
return *this;
}
bigint operator = (ll b)
{
CL();
do
{
s[++l] = b % base;
b /= base;
} while (b > 0);
return *this;
}
bigint operator + (const int &b)
{
bigint c = *this;
ll x = b;
for (int i = 1; i <= l && x; i++)
{
x = x + c.s[i];
c.s[i] = x % base;
x /= base;
}
if(x)c.s[++c.l] = x;
return c;
}
bigint operator + (const ll &b)
{
bigint c = *this;
ll x = b;
for (int i = 1; i <= l && x; i++)
{
x = x + c.s[i];
c.s[i] = x % base;
x /= base;
}
if (x)
c.s[++c.l] = x;
return c;
}
bigint operator + (bigint &b)
{
if (b.l < 3)
return *this + b.toint();
bigint c;
ll x = 0;
int k = l < b.l ? b.l : l;
c.CL();
c.l = k;
for (int i = 1; i <= k; i++)
{
x = x + s[i] + b.s[i];
c.s[i] = x % base;
x /= base;
}
if (x)
c.s[++c.l] = x;
return c;
}
bigint operator / (const int &b)
{
bigint c;
ll x = 0;
c.CL();
for (int i = l; i; i--)
{
c.s[i] = (x * base + s[i]) / b;
x = (x * base + s[i]) % b;
}
for (c.l = l; !c.s[c.l] && c.l > 1; c.l--);
return c;
}
bigint operator % (const int &b)
{
bigint c;
ll x = 0;
c.CL();
for (int i = l; i; i--)
x = (x * base + s[i]) % b;
return c = x;
}
bool operator > (const bigint &b) const
{
if (l ^ b.l)
return l > b.l;
for (int i = l; i; i--)
if (s[i] ^ b.s[i])
return s[i] > b.s[i];
return false;
}
bigint operator += (bigint &b)
{
return *this = *this + b;
}
bool operator > (int b) const{
bigint c;return *this > (c = b);
}
};
//以上皆为高精度部分
bigint a;
int num[350],tmp[350];bigint dp[350][2][350];
bool pan[350][2][350];
inline bigint dfs(int st,int len,int ok,bool limit){
bigint ans,pp;ans=0;pp=0;
if(len<1){//边界
if(ok&&st>0)ans=1;
return ans;
}
if(!limit&&pan[len][ok][st])return dp[len][ok][st];//返回所记录的值
int ed=limit?num[len]:1;//处理枚举上限
for(int i=0;i<=ed;i++){
tmp[len]=i;//记录每次选的数,方便判断是否满足回文
if(st==len&&!i)pp=dfs(st-1,len-1,ok,limit&&i==ed),ans+=pp;//如果一直都没选数
else pp=dfs(st,len-1,(ok&&len<=st/2)?tmp[st-len+1]==i:ok,limit&&i==ed),ans+=pp;//如果选了数
}
if(!limit)dp[len][ok][st]=ans,pan[len][ok][st]=1;//记录
return ans;
}
int main(){
a.re_l();ll Lenn=0;
while(a>0){num[++Lenn]=(a%2).toint();a=(a/2);}//转成2进制存起来
bigint ans=dfs(Lenn,Lenn,1,1);
ans.pr();
return 0;
}
【题解】Kathy函数 [BZOJ1223] [P2235] [HNOI2002]的更多相关文章
- bzoj 1223: [HNOI2002]Kathy函数 数位DP 高精度
1223: [HNOI2002]Kathy函数 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 207 Solved: 90[Submit][Stat ...
- [bzoj1223] [HNOI2002]Kathy函数
首先由题解可得TAT,f(i)=i当且仅当i在二进制下为回文串. 那么问题就变成了1~n中有多少个二进制下的回文串. 把m转成2进制后就是正常的统计了= =. f[i]表示二进制下,有多少个i位的回文 ...
- 洛谷P2235 [HNOI2002]Kathy函数
传送门 题解 // luogu-judger-enable-o2 //minamoto #include<cstdio> #include<cstring> using nam ...
- [HNOI2002] Kathy 函数
数位 DP 套路题,求二进制下区间内回文串个数. 设 dp[][][] 表示到第几位时,是否为回文数,去掉前导零后共几位.之后到边界时判断是否为回文数计入贡献. 一开始不知道答案统计要高精,于是后来就 ...
- 洛谷$P$2235 $Kathy$函数 $[HNOI2002]$ 数位$dp$
正解:数位$dp$ 解题报告: 传送门$qwq$ $HNOI$的题从02年就这么神了嘛$QAQ$,,, 嗷对了这题如果看出了一个结论就是个数位$dp$板子,,,?但是结论很神我$jio$得挺难看出来的 ...
- 【CJOJ2484】【Luogu2805】最小函数值(函数最小值)
题面 Description 有n个函数,分别为F1,F2,...,Fn.定义 Fi(x)=Aix2+Bix+Ci(x∈N∗)Fi(x)=Aix2+Bix+Ci(x∈N∗) .给定这些Ai.Bi和Ci ...
- 「题解」300iq Contest 2 H. Honorable Mention
本文将同步发布于: 洛谷博客: csdn: 博客园: 简书. 题目 题目链接:gym102331H. 题意概述 给定一个长度为 \(n\) 的序列 \(a\),有 \(q\) 次询问,每次询问给定三个 ...
- Noip前的大抱佛脚----赛前任务
赛前任务 tags:任务清单 前言 现在xzy太弱了,而且他最近越来越弱了,天天被爆踩,天天被爆踩 题单不会在作业部落发布,所以可(yi)能(ding)会不及时更新 省选前的练习莫名其妙地成为了Noi ...
- 数位DP学习笔记
数位DP学习笔记 什么是数位DP? 数位DP比较经典的题目是在数字Li和Ri之间求有多少个满足X性质的数,显然对于所有的题目都可以这样得到一些暴力的分数 我们称之为朴素算法: for(int i=l_ ...
随机推荐
- Elasticasearch Web管理工具-Cerebro
cerebro是一个使用Scala,Play Framework,AngularJS和Bootstrap构建的开源(MIT许可)elasticsearch web管理工具.需要Java 1.8或更高版 ...
- 任务型对话(二)—— DST(对话状态追踪)
1,概述 关于任务型对话的简介看任务型对话(一)—— NLU(意识识别和槽值填充). 首先我们来看下对话状态和DST的定义. 对话状态:在$t$时刻,结合当前的对话历史和当前的用户输入来给出当前每个s ...
- MAZE(2019年牛客多校第二场E题+线段树+矩阵乘法)
题目链接 传送门 题意 在一张\(n\times m\)的矩阵里面,你每次可以往左右和下三个方向移动(不能回到上一次所在的格子),\(1\)表示这个位置是墙,\(0\)为空地. 现在有\(q\)次操作 ...
- python相关资源
http://blog.csdn.net/ken_wanglin/article/details/53095967 http://www.infoq.com/cn/articles/Python-wr ...
- scrapy 改 scrapy-redis
1.spider 修改 class CgysSpider(scrapy.Spider): name = 'clispider' start_urls = ['https://search.bilibi ...
- 性能测试:TPS和QPS的区别
做测试,各种ps,jps,tps,qps,rps,hps,你理解几个? 技术群里,问得最多的就是tps和qps,有相似的地方,也有差异的地方,我简单谈下自己的理解.(由于比较忙,下面部分摘抄自网络) ...
- excel隔行选中内容如何操作
查看log日志是站长经常要做的事,从日志中可以发现很多问题,spider最近有没来爬,爬了哪些url,哪些页面不存在了等等,这些都可以看得到.然后你要根据不同的情况采取相应的措施.ytkah喜欢把这些 ...
- 常用dos命令(2)
文件管理 type 显示文本文件的内容. copy 将一份或多份文件复制到另一个位置. del 删除一个或数个文件. move 移动文件并重命名文件和目录.(Windows XP Home Editi ...
- ES6学习笔记 -- 尾调用优化
什么是尾调用? 尾调用(Tail Call)是函数式编程的一个重要概念,就是指某个函数的最后一步是调用另一个函数. function f(x) { return g(x) } 如上,函数 f 的最后一 ...
- three.js 设置透明度
原文:https://www.cnblogs.com/amy2011/p/6148736.html 材质: 材质就像物体的皮肤,决定了几何体的外表,例如是否像草地/金属,是否透明,是否显示线框等 Th ...