[bzoj1853]幸运数字

容易发现幸运数字只有1024个,暴力标记倍数还是会tle的

容斥,即从中任选i个的lcm,复杂度为$o(2^1024)$

剪枝一:当答案超过1024就不用算了

剪枝二:当某个数是另一个数的倍数时就删掉

(另外求lcm可能会爆long long,由于爆了long long一定不合法,因此可以用除法来判定)

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define ll long long
 4 ll x,y,ans,a[10005];
 5 ll gcd(ll x,ll y){
 6     if (!y)return x;
 7     return gcd(y,x%y);
 8 }
 9 void tot(ll k){
10     if (k>y)return;
11     if (k)a[++a[0]]=k;
12     tot(k*10+6);
13     tot(k*10+8);
14 }
15 void dfs(int k,int s,ll val){
16     if (k>a[0]){
17         ans+=(y/val-(x-1)/val)*(s*2-1);
18         return;
19     }
20     dfs(k+1,s,val);
21     ll g=val/gcd(val,a[k]);
22     if (g<=y/a[k])dfs(k+1,s^1,a[k]*g);
23 }
24 int main(){
25     scanf("%lld%lld",&x,&y);
26     tot(0);
27     sort(a+1,a+a[0]+1);
28     for(int i=a[0];i;i--)
29         for(int j=1;j<i;j++)
30             if (a[i]%a[j]==0)a[i]=0;
31     sort(a+1,a+a[0]+1);
32     for(int i=1;i<=a[0]/2;i++)swap(a[i],a[a[0]-i+1]);
33     while (!a[a[0]])a[0]--;
34     dfs(1,0,1);
35     printf("%lld",ans+(y-x+1));
36 }
View Code

 

posted @ 2019-11-16 21:26  PYWBKTDA  阅读(140)  评论(0编辑  收藏  举报