题目背景
四川NOI省选2010
题目描述
在中国,很多人都把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
输出样例#1:
2
说明
对于30%的数据,保证1<=a<=b<=1000000
对于100%的数据,保证1<=a<=b<=10000000000
思路:打表+容斥原理+剪枝
先打一张幸运数字的表;
然后容斥原理求值;
剪枝:有些(是前面的幸运数字的倍数)幸运数字是无用的。
从大到小排。
超出边界的最小公倍数是无用的。
代码实现:
1 #include2 #include 3 #define LL long long 4 using namespace std; 5 LL l,r,ans; 6 LL a,b; 7 LL s[3000],ss; 8 LL fs[3000],fss; 9 LL lch,ret;10 char ch[30];11 LL read(){12 while(ch[0]=getchar(),ch[0]<'0'||ch[0]>'9');13 lch=1,ret=ch[0]-'0';14 while(ch[lch]=getchar(),ch[lch]>='0'&&ch[lch]<='9') ret=ret*10+ch[lch]-'0',lch++;15 return ret;16 }17 void write(LL x){18 if(!x) return;19 write(x/10);20 putchar(x%10+'0');21 }22 void dfs(LL x){23 if(x>r) return;24 if(x) s[ss++]=x;25 dfs(x*10+6);26 dfs(x*10+8);27 }28 inline LL gcd(LL x,LL y){ return y?gcd(y,x%y):x;}29 void get_ans(LL k,LL x,LL y){30 if(x>r) return;31 if(k) ans+=(k&1)?r/x-(l-1)/x:(l-1)/x-r/x;32 for(LL i=y;i
bzoj | 74 | 1950429 | J_william | 872 KB | 672 MS | 1188 B | 2017-03-26 18:04:28 |
LONG LONG 真恶心!
题目来源:洛谷,bzoj