1. 程式人生 > >【GDKOI2012模擬02.01】數字

【GDKOI2012模擬02.01】數字

想了2個小時。。。都想到數位DP去了,雖然沒打(但是我瘋了)
打表找規律。比賽時打了個表發現每九個的D()都是一迴圈(1~9)
然後想著怎麼做,先打了個暴力然後在想,沒想到的是:
如果x為喜歡的數的話,那麼x+22680也是喜歡的數。
為什麼?
設x=a·D(a),那麼x+22680=a·D(a)+22680
因為D(a)為1~9中的一個,所以D(a)為22680的倍數
那麼a*D(a)+22680=(a+22680/D(a))*D(a),所以沒有問題!
所以我們只需要先預處理一下1~22680的喜歡的數即可。
每次l~r手動統計答案即可。

上標:

#include<cstdio>
#include<cstring> #define ll long long #define L 22680 using namespace std; ll l,r,ans=0; int T,b[22681],tot=0; int D(int x) {return (x-1)%9+1;} int main() { // freopen("number.in","r",stdin); // freopen("number.out","w",stdout); for (int i=1;i<=L;i++) { bool bz=0; if (i%9==0 && D(i/
9)==9) bz=1; else if (i%8==0 && D(i/8)==8) bz=1; else if (i%7==0 && D(i/7)==7) bz=1; else if (i%6==0 && D(i/6)==6) bz=1; else if (i%5==0 && D(i/5)==5) bz=1; else if (i%4==0 && D(i/4)==4) bz=1; else if (i%3==0 && D(i/3)==3) bz=1; else if (i%2==0 &&
D(i/2)==2) bz=1; else if (D(i)==1) bz=1; if (bz) b[++tot]=i; } scanf("%d",&T); while (T--) { scanf("%lld %lld",&l,&r); ll fir=l/L*L,sec=0;ans=0; for (int i=1;i<=tot;i++) { sec=fir+b[i]; if (sec<l) { sec+=L; if (sec<=r) ans+=(r-sec)/22680+1; continue; } if (sec>r) break; ans+=(r-sec)/22680+1; } printf("%lld\n",ans); } return 0; }