1. 程式人生 > >2018.10.05 bzoj2393: Cirno的完美算數教室(容斥原理+搜尋)

2018.10.05 bzoj2393: Cirno的完美算數教室(容斥原理+搜尋)

傳送門 經典題目。 顯然滿足題意的數最多不超過1024個。 然後對於兩個數a,ba,b,如果aabb的倍數,那麼就不必計算aa的貢獻。 處理出來之後容斥原理+爆搜剪枝就能過了。 程式碼:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll L,R,divv[1050],Div[1050],ans=0,f=1;
bool BK;
int tot=0,cnt=0;
inline void dfs(ll sum){
	if(sum>R)return;
	if(sum)divv[++tot]=sum;
	dfs
(sum*10+2),dfs(sum*10+9); } inline ll gcd(ll a,ll b){while(b){ll t=a;a=b,b=t%a;}return a;} inline void dfs(int pos,int dep,ll mul){ if(mul>R)return; if(!dep){if(mul)ans+=f*(R/mul-(L-1)/mul),BK=0;return;} if(pos==cnt+1)return; dfs(pos+1,dep,mul),dfs(pos+1,dep-1,mul/gcd(mul,Div[pos])*Div[pos]); } int
main(){ cin>>L>>R,dfs(0),sort(divv+1,divv+tot+1); for(int i=1;i<=tot;++i){ bool f=true; for(int j=i-1;j;--j)if(divv[i]%divv[j]==0){f=false;break;} if(f)Div[++cnt]=divv[i]; } for(int i=1;i<=cnt;++i,f*=-1){ BK=1,dfs(1,i,1); if(BK)break; } cout<<ans; return 0; }