列表

详情


NC20278. [SCOI2010]幸运数字

描述

在中国,很多人都把6和8视为是幸运数字!lxhgww也这样认为,于是他定义自己的“幸运号码”是十进制表示中只包含数字6和8的那些号码,比如68,666,888都是“幸运号码”!
但是这种“幸运号码”总是太少了,比如在[1,100]的区间内就只有6个(6,8,66,68,86,88),于是他又定义了一种“近似幸运号码”。
lxhgww规定,凡是“幸运号码”的倍数都是“近似幸运号码”,当然,任何的“幸运号码”也都是“近似幸运号码”,比如12,16,666都是“近似幸运号码”。 现在lxhgww想知道在一段闭区间[a, b]内,“近似幸运号码”的个数。

输入描述

输入数据是一行,包括2个数字a和b

输出描述

输出数据是一行,包括1个数字,表示在闭区间[a, b]内“近似幸运号码”的个数

示例1

输入:

1 10

输出:

2

示例2

输入:

1234 4321

输出:

809

原站题解

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

C++(g++ 7.5.0) 解法, 执行用时: 139ms, 内存消耗: 544K, 提交时间: 2023-05-10 15:03:07

#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cmath>
#define abs(x) ((x)>0?(x):-(x))
using namespace std;
long long a,b,t,cnt,num[100000],c[100000],ans;
long long gcd(long long a,long long b)
{
	while (b)
	{
		long long c=a%b;
		a=b;
		b=c;
	}
	return a;
}
void solve(int k,long long s)
{
	if (abs(s)>b)	return;
	if (k>t)
	{
		if (abs(s)>1)	ans+=b/s-(a-1)/s;
		return;
	}
	solve(k+1,-s/gcd(abs(s),c[k])*c[k]);
	solve(k+1,s);
}
void dfs(long long s)
{
	if (s>b)	return;
	if (s>1)	num[++cnt]=s;
	dfs(s*10+6);
	dfs(s*10+8);
}
int main()
{
	cin>>a>>b;
	cnt=0;
	dfs(0);
	sort(num+1,num+cnt+1);
	t=0;
	for (int i=1;i<=cnt;++i)
	{
		bool flag=1;
		for (int j=1;j<i;++j)
			if (num[i]%num[j]==0)
				flag=0;
		if (flag)	c[++t]=num[i];
	}
	for (int i=t;i>=t/2;--i)
		swap(c[i],c[t-i+1]);
	ans=0;
	solve(1,-1);
	cout<<ans<<endl;
	return 0;
}

C++(clang++ 11.0.1) 解法, 执行用时: 85ms, 内存消耗: 444K, 提交时间: 2023-04-13 20:30:40

#include <bits/stdc++.h>
using namespace std;
long long s[10010],num[10010],a,b,ans = 0;
int cnt = -1,n = 0;
void dfs(long long p)
{
	if(p > b) return;
	num[++cnt] = p;
	dfs(p*10+6);
	dfs(p*10+8);
}
void get(int t,long long p,int u)
{
	ans += (b/p - (a-1)/p) * u;
	for(int i = t+1;i <= n;++i) 
		if(1.0*p/__gcd(p,s[i])*s[i] <= b)
			get(i,p/__gcd(p,s[i])*s[i],-u);	
}
int main()
{
	scanf("%lld%lld",&a,&b);
	dfs(0);
	sort(num+1,num+cnt+1);
	for(int i = 1;i <= cnt;++i)
	{
		if(!num[i]) continue; 
		for(int j = i+1;j <= cnt;++j)
			if(num[j] % num[i] == 0)	
				num[j] = 0;
	}
	for(int i = 1;i <= cnt;++i) 
		if(num[i])
			s[++n] = num[i];
	reverse(s + 1,s + n + 1);
	get(0,1,1);
	cout<<b - a + 1 - ans;		
	return 0;
} 

上一题