就是爆搜嘛。
先从大到小排个序能减去dfs树上很大的一部分。这个技巧要掌握。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #define maxn 100500 using namespace std; long long l,r,num[maxn],s[maxn],t1=0,t2=0,t,ans=0; bool vis[maxn]; void get_baka(long long bit,long long nums) { if ((bit>t) || (nums>r)) return; if (nums) num[++t1]=nums; get_baka(bit+1,nums*10+2); get_baka(bit+1,nums*10+9); } long long gcd(long long a,long long b) { if (!b) return a; return gcd(b,a%b); } long long lcm(long long a,long long b) { return a*b/gcd(a,b); } void dfs(long long now,long long num,long long val) { if (now==t2+1) { if (num!=1) ans+=((r/num)-((l-1)/num))*val; return; } dfs(now+1,num,val); long long aft=lcm(num,s[now]); if (aft<=r) dfs(now+1,aft,val*(-1)); } int main() { scanf("%lld%lld",&l,&r); t=(long long)(log(r)/log(10))+1; get_baka(0,0); sort(num+1,num+t1+1); for (long long i=1;i<=t1;i++) { if (vis[i]) continue; s[++t2]=num[i]; for (long long j=i+1;j<=t1;j++) { if (!num[j]%num[i]) vis[j]=true; } } for (int i=1;i<=t2;i++) num[i]=s[t2-i+1]; for (int i=1;i<=t2;i++) s[i]=num[i]; dfs(1,1,-1); printf("%lld\n",ans); return 0; }