【bzoj1853】: [Scoi2010]幸运数字 数论-容斥原理

【bzoj1853】: [Scoi2010]幸运数字

预处理出所有幸运数字然后容斥原理

但是幸运数字是2logn个数的 直接搞会炸

所以把成倍数的处理掉

然后发现还是会T 所以数字要从大到小处理会快很多 我也不知道为什么

还有就是剪枝的时候要开double 不然爆longlong

 1 /* http://www.cnblogs.com/karl07/ */
 2 #include <cstdlib>
 3 #include <cstdio>
 4 #include <cstring>
 5 #include <cmath>
 6 #include <map>
 7 #include <algorithm>
 8 using namespace std;
 9 #define ll long long
10 
11 const ll N=10000000005;
12 ll num[5000];
13 ll a,b,cnt,ans,cc;
14 
15 ll gcd(ll a,ll b){ return b==0 ? a : gcd(b,a%b);}
16 ll lcm(ll a,ll b){ return a/gcd(a,b)*b;}
17 
18 void dfs(ll x,ll n){
19     if (x>n) return;
20     num[++cnt]=x;
21     dfs(x*10+6,n);
22     dfs(x*10+8,n);
23 }
24 
25 void rc(ll c,ll x,ll n,ll nw){
26     if (x==0){
27         if (c==0) return;
28         if (c&1) ans+=n/nw; else ans-=n/nw;
29         return;
30     }
31     if ((double)nw/gcd(num[x],nw)*num[x] <= n) rc(c+1,x-1,n,lcm(nw,num[x]));
32     rc(c,x-1,n,nw);
33 }
34 
35 ll work(ll n){
36     if (n<6) return 0;
37     cnt=0;ans=0;
38     dfs(6,n);dfs(8,n);cc=cnt;
39     num[0]=1;
40     sort(num+1,num+cnt+1);
41     for (int i=1;i<=cnt;i++){ 
42         for (int j=i+1;j<=cnt && num[i]!=N;j++){
43             if (num[j]%num[i]==0) num[j]=N,cc--;
44         }
45     }
46     sort(num+1,num+cnt+1);
47     rc(1,cc-1,n,num[cc]);
48     rc(0,cc-1,n,1);
49     return ans;
50 }
51 
52 int main(){
53     scanf("%lld%lld",&a,&b);
54     printf("%lld\n",work(b)-work(a-1));
55     return 0;
56 }
View Code

 

posted @ 2017-03-22 19:26  karl07  阅读(158)  评论(0编辑  收藏  举报