Luogu P2567 [SCOI2010]幸運數字 容斥+腦子


雙倍經驗:BZOJ 2393 Cirno的完美算數教室


 

做法:先把$[1,r]$中所有的幸運數字篩出來,然后用這些幸運數字來篩$[l,r]$中的近似幸運號碼;

剪枝:當一個幸運數字$a[i]$是另一個幸運數字$a[j]$的倍數時,那么應該把$a[i]$去掉;

貢獻用容斥搞一下好了(就是dfs部分)。。

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<cctype>
#include<cstdlib>
#include<vector>
#include<map>
#include<set>
#define ll long long
#define R register ll
static char B[1<<15],*S=B,*D=B;
#define getchar() (S==D&&(D=(S=B)+fread(B,1,1<<15,stdin),S==D)?EOF:*S++)
using namespace std;
inline ll g() {
    R ret=0,fix=1; register char ch; while(!isdigit(ch=getchar())) fix=ch=='-'?-1:fix;
    do ret=ret*10+(ch^48); while(isdigit(ch=getchar())); return ret*fix;
} ll q[5010],l,r,ans; bool vis[5010]; int tot; 
inline void PRE(ll x) {if(x>r) return ; if(x) q[++tot]=x; PRE(x*10+6); PRE(x*10+8);}
inline ll gcd(ll a,ll b) {return b?gcd(b,a%b):a;}
inline bool cmp(const ll& a,const ll& b) {return a>b;}
inline void dfs(int x,int d,ll L) {
    if(x==tot) return ; ++x; dfs(x,d,L); d^=1;
    if(vis[x]) return ; L=L*q[x]/gcd(L,q[x]);
    if(L<=0||L>r) return ; if(d) ans+=r/L-(l-1)/L;
    else ans-=r/L-(l-1)/L; dfs(x,d,L);
}
signed main() {
    l=g(),r=g(); PRE(0); sort(q+1,q+tot+1,cmp);
    for(R i=1;i<=tot;++i) for(R j=i+1;j<=tot;++j) if(q[i]%q[j]==0) {vis[i]=1; break; }
    dfs(0,0,1); printf("%lld\n",ans);
}

2019.06.04別頹。


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2021 ITdaan.com