JZOJ5379. 【NOIP2017提高A组模拟9.21】Victor爱数字
2017-09-22 22:43
471 查看
Description
Victor 是一名热爱数字的同学。他最近在思考这样一个问题:一个字符串是回文的当且仅当它倒过来还和原来相同。那么如果一个数的数串没有一个长度超过1 的子串是回文串的话,它就是palindrome-free 的。例如:16276 是palindrome-free的,而17276 不是,因为它包含了回文串727。
Victor 想知道在a 到b 的区间内,有多少个数是palindrome-free 的。
Input
从文件numbers.in 中读入数据。包括两个数字a,b。
Output
输出到文件numbers.out 中。输出包含一个整数:区间a,…,b 中palindrome-free 的数的总个数(包括a,b)。
Sample Input
输入1:123 321
输入2:
123456789 987654321
Sample Output
输出1:
153
输出2:
167386971
Data Constraint
对于16% 的数据,b - a <= 200。对于24% 的数据,b - a <= 10^5。
对于32% 的数据,b - a <= 10^6。
对于100% 的数据,0 <= a <= b <= 10^18
题解
很显然,这是数位dp。将问题变为求1~r的减去1~(l-1)的。
如果不出现回文超过1的串,其实只需要判断是否存在
长度为1或者2的就可以了。
设fi,s1,s2
表示当前是第i位,不存在前导0,末尾两位分别是s1,s2。
转移就枚举一个k,表示之前的那一位选了什么。
code
#include<queue> #include<cstdio> #include<iostream> #include<algorithm> #include <cstring> #include <string.h> #include <cmath> #include <math.h> #define ll long long #define N 150003 #define db double #define P putchar #define G getchar #define mo 1000000007 using namespace std; char ch; void read(ll &n) { n=0; ch=G(); while((ch<'0' || ch>'9') && ch!='-')ch=G(); ll w=1; if(ch=='-')w=-1,ch=G(); while('0'<=ch && ch<='9')n=(n<<3)+(n<<1)+ch-'0',ch=G(); n*=w; } int max(int a,int b){return a>b?a:b;} int min(int a,int b){return a<b?a:b;} void write(ll x) { if(x>9) write(x/10); P(x%10+'0'); } ll a,b,ans; ll f[23][13][13]; ll work(ll x) { if(x<10)return x+1; ll t[23],len=0,g=1; while(x) { t[++len]=x%10; x/=10; } for(int i=1;i<=len/2;i++) swap(t[i],t[len-i+1]); t[0]=10;t[len+1]=-123; memset(f,0,sizeof(f)); //f[1][0][0]=1; for(int i=1;i<=len;i++) { for(int s1=0;s1<10;s1++) for(int s2=0;s2<10;s2++) { if(s1==s2)continue; for(int k=0;k<=10;k++) if(k!=s1 && k!=s2)f[i][s1][s2]+=f[i-1][k][s1]; } /*if(i>1) { for(int k=0;k<10;k++) f[i][10][k]++; }*/ for(int k=i==1;k<t[i];k++) if(t[i-1]!=k && t[max(i-2,0)]!=k)f[i][t[i-1]][k]+=g; if(t[i]==t[i-1] || t[i-2]==t[i])g=0; } ll ans=g; for(int i=0;i<10;i++) for(int j=0;j<10;j++) ans+=f[len][i][j]; return ans; } ll sum(ll x) { ll ans=work(x),t=10; x/=10; while(x>0)ans+=work(t-1),t*=10,x/=10; return ans; } int main() { freopen("numbers.in","r",stdin); freopen("numbers.out","w",stdout); read(a);read(b); printf("%lld",sum(b)-sum(a-1)); //while(1)read(a),write(sum(a)),P('\n'); }
相关文章推荐
- JZOJ 5379. 【NOIP2017提高A组模拟9.21】Victor爱数字
- JZOJ5379. 【NOIP2017提高A组模拟9.21】Victor爱数字 数位DP
- 5379. 【NOIP2017提高A组模拟9.21】Victor爱数字 (2017.9B组)
- JZOJ5381. 【NOIP2017提高A组模拟9.21】传送蛋糕
- JZOJ5400. 【NOIP2017提高A组模拟10.7】Repulsed 树型DP+贪心
- JZOJ 5401. 【NOIP2017提高A组模拟10.8】Star Way To Heaven
- JZOJ 5376. 【NOIP2017提高A组模拟9.19】Candy
- 【JZOJ4930】【NOIP2017提高组模拟12.18】C
- 【jzoj5333】【NOIP2017提高A组模拟8.23】【大新闻】【可持久化线段树】
- jzoj5331 【NOIP2017提高A组模拟8.23】壕游戏
- 【JZOJ5329】【NOIP2017提高A组模拟8.22】时间机器
- jzoj5336 【NOIP2017提高A组模拟8.24】提米树 (dfs序dp,奇异姿势dp)
- JZOJ5390. 【NOIP2017提高A组模拟9.26】逗气 单调队列
- JZOJ 5405.【NOIP2017提高A组模拟10.10】Permutation
- JZOJ5394. 【NOIP2017提高A组模拟10.5】Ping 树上差分 树状数组
- JZOJ 4932. 【NOIP2017提高组模拟12.24】B
- 【JZOJ4924】【NOIP2017提高组模拟12.17】向再见说再见
- JZOJ5187. 【NOIP2017提高组模拟6.30】tty's maze
- 【JZOJ5287】【NOIP2017提高组模拟】最短路
- 【jzoj5338】【NOIP2017提高A组模拟8.25】【影子】【点分治】