人们选择手机号码时都希望号码好记、吉利。比如号码中含有几位相邻的相同数字、不含谐音不吉利的数字等。手机运营商在发行新号码时也会考虑这些因素,从号段中选取含有某些特征的号码单独出售。为了便于前期规划,运营商希望开发一个工具来自动统计号段中满足特征的号码数量。 工具需要检测的号码特征有两个:号码中要出现至少 3 个相邻的相同数字,号码中不能同时出现 8 和 4。号码必须同时包含两个特征才满足条件。满足条件的号码例如:13000988721、23333333333、14444101000。而不满足条件的号码例如:1015400080、10010012022。 手机号码一定是 11 位数,前不含前导的 0。工具接收两个数 L 和 R,自动统计出 [L,R] 区间内所有满足条件的号码数量。L 和 R 也是 11 位的手机号码。
有多行数据输入 每行为空格分隔的 2 个正整数 L, R。
输出内容只有一行,为 1 个整数,表示满足条件的手机号数量。
12121284000 12121285550
5
满足条件的号码:12121285000、12121285111、12121285222、12121285333、12121285550 对于 100% 的测试数据,10^10 ≤ L ≤ R < 10^11
#include <bits/stdc++.h> #define ll long long using namespace std; ll dp[11][3][10][2][2],L,R; int bit[30]; ll dfs(int pre,int len,int pos,bool is4,bool is8,bool isok){ if (pos<0) return (len>2&&!(is4&&is8)); if (is4&&is8) return 0; if (isok&&dp[pos][len][pre][is4][is8]+1) return dp[pos][len][pre][is4][is8]; ll sum=0; int l,mxn=(isok)?9:bit[pos]; for (int i=mxn;i>=0;--i){ if (len>=3) l=3; else if (i==pre) l=len+1; else l=1; sum+=dfs(i,l,pos-1,is4||i==4,is8||i==8,isok||i<mxn); } if (isok) dp[pos][len][pre][is4][is8]=sum; return sum; } ll solve(ll n) { if (n <= 9999999999) return 0; for (int i=0;i<11;++i) bit[i]=n%10,n/=10; ll sum = 0; for (int i=1;i<=bit[10];++i) sum+=dfs(i,1,9,i==4,i==8,i<bit[10]); return sum; } int main() { memset(dp,-1,sizeof dp); while(~scanf("%lld%lld",&L,&R)) { printf("%lld\n",solve(R)-solve(L-1)); } return 0; }