列表

详情


NC19945. [CQOI2016]手机号码

描述

人们选择手机号码时都希望号码好记、吉利。比如号码中含有几位相邻的相同数字、不含谐音不吉利的数字等。手机运营商在发行新号码时也会考虑这些因素,从号段中选取含有某些特征的号 码单独出售。为了便于前期规划,运营商希望开发一个工具来自动统计号段中满足特征的号码数 量。
工具需要检测的号码特征有两个:号码中要出现至少3个相邻的相同数字,号码中不能同时出现8和4。号码必须同时包含两个特征才满足条件。满足条件的号码例如:13000988721、 23333333333、14444101000。而不满足条件的号码例如:1015400080、10010012022。 手机号码一定是11位数,前不含前导的0。工具接收两个数L和R,自动统计出[L,R]区间 内所有满足条件的号码数量。L和R也是11位的手机号码。

输入描述

输入文件内容只有一行,为空格分隔的2个正整数L,R。
10^10 ≤ L ≤ R < 10^11

输出描述

输出文件内容只有一行,为1个整数,表示满足条件的手机号数量。

示例1

输入:

12121284000 12121285550

输出:

5

说明:

样例解释
满足条件的号码: 12121285000、 12121285111、 12121285222、 12121285333、 12121285550

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++(g++ 7.5.0) 解法, 执行用时: 4ms, 内存消耗: 744K, 提交时间: 2022-12-30 20:04:10

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=50;
int f[2][25][2][2][2][10][10],s[N],cnt;
int dfs(int len,int done,int c8,int c4,int ky,int l1,int l2)
{
	if(c8&&c4) return 0;
	if(!len) return ky;
	if(~f[done][len][c8][c4][ky][l1][l2]) return f[done][len][c8][c4][ky][l1][l2];
	int ed=done?s[len]:9,res=0;
	for(int i=0;i<=ed;++i)
		res+=dfs(len-1,done&&(i==ed),c8||(i==8),c4||(i==4),ky||((l1==i)&&(l2==i)),l2,i);
	f[done][len][c8][c4][ky][l1][l2]=res;
	return res;
}
inline int dp(int x)
{
	if(x<1e10) return 0;
	cnt=0;
	while(x) s[++cnt]=x%10,x/=10;
	memset(f,-1,sizeof f);
	int res=0;
	for(int i=1;i<=s[cnt];++i)
		res+=dfs(10,i==s[cnt],i==8,i==4,0,0,i);
	return res;
}
signed main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	int a,b;
	cin>>a>>b;
	cout<<dp(b)-dp(a-1)<<endl;
}

C++(clang++ 11.0.1) 解法, 执行用时: 4ms, 内存消耗: 820K, 提交时间: 2022-12-31 16:19:56

#include<bits/stdc++.h>
#define ll long long
using namespace std;
int a[15];
ll dp[15][15][15][2][2][2][2];
ll Dfs(int n,int up,int last,bool limst,bool t4,bool t8,bool tf)
{
	if(t4&&t8)return 0;
	if(n==0)return tf;
	if(dp[n][up][last][limst][t4][t8][tf]!=-1)
	return dp[n][up][last][limst][t4][t8][tf];
	ll ret=0;
	for(int i=limst?9:a[n];i>=(n==11);i--)
		ret+=Dfs(n-1,i,up,limst||(i<a[n]),t4||(i==4),t8||(i==8),tf||(i==up&&i==last));
	return dp[n][up][last][limst][t4][t8][tf]=ret;
}
ll solve(ll m)
{
	memset(dp,-1,sizeof(dp));
	int pos=0;
	if(m<1e10)return 0;
	while(m)a[++pos]=m%10,m/=10;
	return Dfs(pos,14,14,0,0,0,0);
}
int main()
{
	ll l,r;
	cin>>l>>r;
	cout<<solve(r)-solve(l-1);
	return 0;
} 

上一题