2020牛客暑期多校訓練營(第七場)H題Dividing(整除分塊法)
阿新 • • 發佈:2020-08-02
2020牛客暑期多校訓練營(第七場)H題Dividing(整除分塊法)
題意:給一個N,K,首先對於所有1,k(1<=k<=K),都是符合要求的,然後所有的符合要求的數的數(n,k),若n+k<N,則(n+k,k)也是好的,若nk<N,則(nk,k)也是好的,求符合要求的數量。
題解:首先可以先寫一寫,舉個栗子,(1,3)。
可以變為(4,3),(3,3)。
現在應該很容易發現,乘法操作已經沒用了,因為乘3必然是3的倍數,一定可以通過加3到達,所以可以寫成兩個不等式。
1+m*k<=N,
m*k<=N,
m表示符合要求的個數,然後暴力列舉k,算出每個m既可,K過大列舉超時,但是我們可以發現k中間有很多的m都相等,呈線性關係,故可用整除分塊優化。
#include<iostream> #define ll long long using namespace std; const ll mod=1e9+7; ll n,k,ans,m,to,now; int main(){ scanf("%lld%lld",&n,&k); for(ll i=2;i<=k;i++){ now=i; m=n/i; if(m==0)break; to=min(n/m,k); i=to; m%=mod; to%=mod; ans=(ans+m*(to-now+1))%mod; //printf("%lld %lld %lld %lld\n",now,to,ans,i); } for(ll i=2;i<=k;i++){ now=i; m=(n-1)/i; if(m==0)break; to=min((n-1)/m,k); i=to; m%=mod; to%=mod; ans=(ans+m*(to-now+1))%mod; //printf("%lld %lld %lld i=%lld\n",now,to,ans,i); } printf("%lld\n",(ans+k+n-1)%mod); }