Description

  

​   给定正整数\(D\),求有多少个正整数\(N\),满足\(rev(N)=N+D\)。

  

​   其中\(rev(N)\)表示将\(N\)的十进制表示翻转来读得到的数(翻转后忽略前导零)。

  

​   答案对\(10^9+7\)取模。

  

​   \(D \le 10^{9}\)

  

  (实际可以做到\(D \le 10^{5000}\))

  

  

  

Solution

  

  ​ 原题\(D \le 10^9\),暴力可过;但DP做法可以应用到更大的范围。

  

  ​

  

  ​ 考虑枚举\(N\)有多少位,记为\(len\)。

  

​   显然\(len\)不能小于\(D\)的位数,否则一定不合法。并且可以证明,\(len\)超过\(D\)的位数的两倍时,就没有数合法了。再者\(len==1\)的时候也显然不合法。所以枚举区间是\([\max (2,|D|),2|D|]\)。

  

​   设计一个DP来计算在\(N\)的长度为\(len\)时,有多少个数满足条件。

  

​   把和式画出来,并从两端向中间标号:

  



  

​   为什么要这么标号?因为既然是翻转,所以确定一组中的一对数\((x,y)\)就可以确定另一对数\((y,x)\)。

  

​   还要考虑进位问题,那么状态里应该有表示进位的东西。

  

​   设\(f_{i,j,k}\)表示第\(i\)组数,其中左边一组数从其右边有无收到进位(\(j=0,1\)),且右边一组数给其左边有无进位(\(k=0,1\)):

  

​  

  

​   枚举状态\(f_{i,j,k}\),正向转移到可去的状态。枚举\(i+1\)组的\(x'\)选0...9,并通过右边一组数的\(k\)和相应位置的\(D\)的数位算出\(y''\)与\(k'\)。再用左边一组数的\(j\)来计算出\(j'\)。如果\(j'<0\)或者\(j'>1\)就说明这个转移不合法,舍弃。因此,每个\(x\)的取值对应了唯一对应(有可能不合法,舍弃)的新状态\(f_{i+1,j',k'}\),将方案数加上即可。

  

​   注意第1组数的\(x\)不可以选0,不然会违背当前正在考虑长度为\(len\)的\(N\)这个前提。

  

​   如果\(len\)是偶数,那么对于\(i=1..\frac{len}{2}\)计算\(f\),答案即为\(f_{\frac{len}2,0,0}+f_{\frac{len}2,1,1}\)

  

​   如果\(len\)是奇数,则先对于\(i=1...\lfloor \frac{len}2 \rfloor\)计算\(f\),先枚举每个最终状态,再枚举最中间一位选择\(0...9\),是否能满足各个进位与否的要求,统计进答案即可。

  

​  

  

​   总时间复杂度\(\mathcal O(\frac{|D|^2}2*10*2*2)=\mathcal O(|D|^220)\),基本上不会跑满。我造数据时测了一下5000可以秒出,题目就开了5000的长度;然后我SUODCX后构造了一组特殊数据,使得\(N\)长度恰好是\(2|D|\)时也有解,几乎把复杂度卡满了,所以这个点只开到了3000(已经可以跑得出了).

  

  

   

Code

  

c++
#include <cstdio>
#include <cstring>
using namespace std;
const int N=10010,MOD=1e9+7;
int d[N];
int f[N][2][2];
inline int max(int x,int y){
return x>y?x:y;
}
void readData(){
static char str[N];
scanf("%s",str+1);
d[0]=strlen(str+1);
for(int i=1;i<=d[0];i++) d[d[0]-i+1]=str[i]-'0';
}
int dp(int n){
int m=n>>1;
for(int i=0;i<=m;i++)
for(int j=0;j<2;j++)
for(int k=0;k<2;k++)
f[i][j][k]=0;
f[0][0][0]=1;
for(int i=0;i<m;i++)
for(int j=0;j<2;j++)
for(int k=0;k<2;k++)
if(f[i][j][k]){
for(int x=0,y,j1,k1;x<10;x++){
k1=x+d[i+1]+k;
y=k1%10;
k1/=10;
j1=10*j+x-y-d[n-i];
if(j1<0||j1>1) continue;
if(!i&&(!x||!y)) continue;
(f[i+1][j1][k1]+=f[i][j][k])%=MOD;
}
}
int res=0;
if(n&1){
int mid=(n+1)>>1;
for(int j=0;j<2;j++)
for(int k=0;k<2;k++)
if(f[m][j][k])
for(int x=0,y;x<10;x++){
y=x+d[mid]+k;
if((x==y%10)&&(y/10==j))
(res+=f[m][j][k])%=MOD;
}
}
else{
for(int j=0;j<2;j++)
(res+=f[m][j][j])%=MOD;
}
return res;
}
void solve(){
int ans=0,maxlen=d[0]<<1;
for(int i=max(2,d[0]);i<=maxlen;i++)
(ans+=dp(i))%=MOD;
printf("%d\n",ans<0?ans+MOD:ans);
}
int main(){
readData();
solve();
return 0;
}

【ARC075F】Mirror的更多相关文章

  1. 【arc075F】Mirrored

    Portal --> arc075_f Solution ​  一开始抱着"我有信仰爆搜就可以过"的心态写了一个爆搜.. ​  但是因为..剪枝和枚举方式不够优秀愉快T掉了q ...

  2. 【ARC075F】Mirrored 搜索/数位dp

    Description ​ 给定正整数DD,求有多少个正整数NN,满足rev(N)=N+Drev(N)=N+D,其中rev(N)rev(N)表示将NN的十进制表示翻转来读得到的数 Input ​ 一个 ...

  3. 【arc075f】AtCoder Regular Contest 075 F - Mirrored

    题意 给定一个数x,问有多少个正整数y,使得rev(y)-y==x 其中rev(x)表示x按位翻转之后得到的数. x<=1e9 做法 首先通过打表发现,这个答案不会很大. 这就说明解相当地松弛. ...

  4. 【转】SQL SERVER 主体,已同步

    转自郭大侠博客:  https://www.cnblogs.com/gered/p/10601202.html 目录 SQL SERVER 基于数据库镜像的主从同步... 1 1.概念... 2 1. ...

  5. 【LeetCode】数学(共106题)

    [2]Add Two Numbers (2018年12月23日,review) 链表的高精度加法. 题解:链表专题:https://www.cnblogs.com/zhangwanying/p/979 ...

  6. 【NLP】Python NLTK获取文本语料和词汇资源

    Python NLTK 获取文本语料和词汇资源 作者:白宁超 2016年11月7日13:15:24 摘要:NLTK是由宾夕法尼亚大学计算机和信息科学使用python语言实现的一种自然语言工具包,其收集 ...

  7. 【JVM】模板解释器--字节码的resolve过程

    1.背景 上文探讨了:[JVM]模板解释器--如何根据字节码生成汇编码? 本篇,我们来关注下字节码的resolve过程. 2.问题及准备工作 上文虽然探讨了字节码到汇编码的过程,但是: mov %ra ...

  8. 【转】(转)【Android】Paint的效果研究

    转自:http://wpf814533631.iteye.com/blog/1847661 (转)[Android]Paint的效果研究 博客分类: android   在Paint中有很多的属性可以 ...

  9. 自定义控件【圆形】圆角 BitmapShader

    关于缩放比例         本例中,我们会为BitmapShader设置了一个matrix,目的是按比例放大或者缩小bitmap,并移动到View控件的中心,我们不会让view的宽高大于我们bitm ...

随机推荐

  1. 32bit 天堂2 windows 2003 server架设教程

    安装环境::[注意:本教程newauth要用不加密的版本] windows 2003 enterprise server 100用户license Microsoft sql server 2000 ...

  2. docker 部署 zookeeper+kafka 集群

    主机三台172.16.100.61172.16.100.62172.16.100.63Docker 版本 当前最新版 # 部署zk有2种方法 ## 注意 \后不要跟空格 一 . 端口映射 172.16 ...

  3. i++ i+=1 i=i+1 汇编代码效率比较

    结论:一样.编译器和编译器之间可能有点区别但是程序不会变. 0x00 一直不清楚到底是因为懒还是真的为了效率,要把" i = i + 1 "写成" i++ "或 ...

  4. 四则运算App--大总结(已完成)

    1. 贡献分分配(20分) 欧泽波:14分,Android的学习,代码的编写,等等 杨洁华:1分,提供学习资料,框架的设计等等 赵泽嘉:3分,提供学习资料,框架的设计等等 林扬滨:2分,提供学习资料, ...

  5. 【CSAPP笔记】12. 高速缓存存储器

    高速缓存存储器 在存储层次结构中,高速缓存存储器,也叫 cache 是最接近 CPU 寄存器的那一块. 更一般而言,缓存(caching)是一个无所不在的技术.缓存的意思是:对于每层的存储设备,位于 ...

  6. 实现二叉树(search)

    ★实验任务 可怜的 Bibi 刚刚回到家,就发现自己的手机丢了,现在他决定回头去搜索 自己的手机. 现在我们假设 Bibi 的家位于一棵二叉树的根部.在 Bibi 的心中,每个节点 都有一个权值 x, ...

  7. Python开发【第五篇】迭代器、生成器、递归函数、二分法

    阅读目录 一.迭代器 1. 迭代的概念 #迭代器即迭代的工具(自定义的函数),那什么是迭代呢? #迭代:指一个重复的过程,每次重复都可以称之为一次迭代,并且每一次重复的结果是下一个迭代的初始值(例如: ...

  8. MaxAlertView 强大的弹框试图

    [链接]https://github.com/MrJalen/MaxAlertView MaxAlertView ) { [MaxAlertView showAlertWithTitle:@" ...

  9. WinForm中DataGridView的快速查找及将指定行显示到第一行

    /// <summary> /// 快速在已绑定的列表查询车辆 /// </summary> /// <param name="sender"> ...

  10. 关于Keil C关键字xdata和data的问题

    1.xdata表示这是一个外部RAM地址内的数据,数据最终将被保存至外部RAM的某个地址单元中:但是,外部RAM只能通过寄存器间接寻址来访问,也就是说,其地址需要保存在内部RAM中(其实或许是SFR中 ...