soj3538 幸运数字 容斥原理应用
2012-09-20 14:20
274 查看
链接:soj3538
【题目大意】:
由6和8组成的数字都是lucky数字,其倍数也是lucky数字。
求给定区间[l,r]有多少个lucky数字。(1 <= l,r <= 10,000,000,000 )
【分析】:
若能求出[1,n]中有多少个lucky数字,问题即解。
先求仅有6和8组成的数字,记为primLucky数,lucky数是primLucky数的若干倍,显然有容斥原理。
Ai表示[1,n]中有多少个是primLucky[i]的倍数的数字的集合。
则由:
n|A1∪A2∪...∪Am|=∑n|Ai|1≤i≤m-∑n|Ai∩Aj|1≤i≤j≤m+∑n|Ai∩Aj∩Ak|-…+(-1)^m-1)n|A1∩A2…∩Am|1≤I,j,k≤m
写成嵌套的形式使用dfs。
生成1到10位数的primLucky数可以:
枚举1到10的长度,定长求primLucky
或者第i长的lucky是由第i-1长的lucky数+尾数为6或者8即可。
附代码:
【题目大意】:
由6和8组成的数字都是lucky数字,其倍数也是lucky数字。
求给定区间[l,r]有多少个lucky数字。(1 <= l,r <= 10,000,000,000 )
【分析】:
若能求出[1,n]中有多少个lucky数字,问题即解。
先求仅有6和8组成的数字,记为primLucky数,lucky数是primLucky数的若干倍,显然有容斥原理。
Ai表示[1,n]中有多少个是primLucky[i]的倍数的数字的集合。
则由:
n|A1∪A2∪...∪Am|=∑n|Ai|1≤i≤m-∑n|Ai∩Aj|1≤i≤j≤m+∑n|Ai∩Aj∩Ak|-…+(-1)^m-1)n|A1∩A2…∩Am|1≤I,j,k≤m
写成嵌套的形式使用dfs。
生成1到10位数的primLucky数可以:
枚举1到10的长度,定长求primLucky
或者第i长的lucky是由第i-1长的lucky数+尾数为6或者8即可。
附代码:
#include <stdio.h> #include <string.h> #include <algorithm> #include <ctype.h> #include <queue> using namespace std; typedef long long ll; const int maxn = 1 << 11 ; ll lucky[maxn] ; int len ; const ll INF = 100000000000000000LL ; inline ll gcd(ll a, ll b) { return b ? gcd(b,a%b) : a ; } ll lcm(ll a,ll b) { if ( INF / a < b ){ return INF;} ll x = gcd(a, b); return a / x * b; } inline bool get(ll &t) { bool flag = 0 ; char c; while(!isdigit(c = getchar())&&c!='-') if( c == -1 ) break ; if( c == -1 ) return 0 ; if(c=='-') flag = 1 , t = 0 ; else t = c ^ 48; while(isdigit(c = getchar())) t = (t << 1) + (t << 3) + (c ^ 48) ; if(flag) t = -t ; return 1 ; } ll l , r ; void init() { ll i , j , k , t , p , q , w ; for( i = k = 0 ; i < 10 ; i++) { //枚举i+1长度的68数 w = i + 1 ; for ( j = 0 ; j < (1<<(i+1)) ; j++) { p = 0 ; t = j ; q = w ; while (q--) { p *= 10 ; if( t & 1 ) p += 8 ; else p += 6 ; t /= 2 ; } lucky[k++] = p ; } } sort(lucky,lucky+k); for( i = p = 1 ; i < k ; i++) { for ( j = 0 ; j < p ; j++) { if ( lucky[i] % lucky[j] == 0 ) break ; } if( j == p ) lucky[p++] = lucky[i] ; } len = p ; } ll dfs(int st,ll pre,ll n) { ll ret = 0 ; int i ; for ( i = 0 ; i < st ; i++) { ll w = lcm(pre, lucky[i]); if (w <= n) ret += n / w - dfs(i, w, n); } return ret; } ll work(ll n) { if( n < 6 ) return 0 ; return dfs(len,1,n) ; } void solve() { printf("%lld\n",work(r)-work(l)); } int main() { init(); while (get(l)) { get(r); l--; solve(); } }
相关文章推荐
- [SCOI2010]幸运数字 [容斥原理 dfs]
- [BZOJ]1853: [Scoi2010]幸运数字 容斥原理
- BZOJ 1853 [Scoi2010]幸运数字 (容斥原理)
- [BZOJ 1853][Scoi2010]幸运数字:容斥原理
- 【BZOJ 1853】 1853: [Scoi2010]幸运数字 (容斥原理)
- [BZOJ1853][Scoi2010]幸运数字(容斥原理)
- 1853: [Scoi2010]幸运数字[容斥原理]
- bzoj 1853: [Scoi2010]幸运数字&&2393: Cirno的完美算数教室【容斥原理】
- BZOJ1853 [Scoi2010]幸运数字 容斥原理
- bzoj1853[Scoi2010]幸运数字 容斥原理
- BZOJ_2393_Cirno的完美算数教室&&BZOJ_1853_[Scoi2010]幸运数字 _深搜+容斥原理
- BZOJ1853 [Scoi2010]幸运数字 [容斥原理]【组合数学】
- 【SCOI2010】【容斥原理】幸运数字
- Bzoj 1853: [Scoi2010]幸运数字 容斥原理,深搜
- 【BZOJ 1853】[Scoi2010]幸运数字 【容斥原理】
- 【BZOJ-1853&2393】幸运数字&Cirno的完美算数教室 容斥原理 + 爆搜 + 剪枝
- bzoj1853: [Scoi2010]幸运数字(容斥原理)
- BZOJ 1853: [Scoi2010]幸运数字(容斥原理)
- ☆【容斥原理】【SCOI2010】幸运数字
- bzoj 1853: [Scoi2010]幸运数字(容斥原理)