2020牛客多校第七場H題Dividing(整除分塊)
阿新 • • 發佈:2020-08-02
連結:https://ac.nowcoder.com/acm/contest/5672/H
題目描述
The following rules define a kind of integer tuple - the Legend Tuple:- (1, k) is always a Legend Tuple, where k is an integer.
- if (n, k) is a Legend Tuple, (n + k, k) is also a Legend Tuple.
- if (n, k) is a Legend Tuple, (nk, k) is also a Legend Tuple.
We want to know the number of the Legend Tuples (n, k) where 1≤n≤N,1≤k≤K
In order to avoid calculations of huge integers, report the answer modulo 10^9+7 instead.
題意:定義了一種元組為可行,給你N,K,計算小於NK的可行組有多少個 對1e9+7取模
題解:根據題目描述我們可以瞭解到(1,k)始終是可行組,然後(1+k,k)(1+2k,k)...是可行組 (k,k)(2k,k)...也是可行組,我們可以理解題意寫出前面幾種可行組
我們可以發現n%k==1 是可行組 (n%k==0) 也是可行組,因此我們只要計算n/k有多少個 和(n-1)/k 也有多少就可以計算出答案,當然這些要滿足大條件 n<N,k<K。
(1,1)(1,2)(1,3)(1,4)(1,5)(1,6)(1,7)(1,8)(1,9)...
(2,1)(2,2)(3,3)(4,4)(5,5)(6,6)
(3,1)(3,2)(4,3)(5,4)
(4,1)(4,2)
(5,1)(5,2)
(6,1)
至此我們可以發現我們只要從1開始列舉(k) 算出n/k有多少種,再判斷n%k的結果是不是0,我們就可以計算出ans,但是題目k的範圍為1e12,時間複雜度為O(k)顯然不行。
這就需要整除分塊,什麼是整除分塊,就是用來計算 (n/i)能整除的有多少個,時間複雜度為O(sqrt(n))
ll diving( ll n){ ll ans=0; for(ll l=3,r;l<=n;l=r+1){ r=n/(n/l); ans+= ( ((r-l+1)%mod) * ((n/l)%mod) ) %mod; ans%=mod; cout<<l<<" "<<r<<" "<<ans<<endl; } return ans%mod; }View Code
此題還有一個坑點 N可以>K,所以我們直接套用上面的程式碼是不行的,會出現大於k的不符合的整除也被計算進來了,
因為我想法 是先把第一行跟左邊兩行加上,從i=3 開始整除,所以前面需要特判k==1。
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); #include <bits/stdc++.h> #define inf 0x3f3f3f3f using namespace std; typedef long long ll; const int maxn=1e3+7; const ll mod =1e9+7; typedef pair<int,int> pii; typedef pair<double,double> pdd; ll diving( ll n,ll k){ ll ans=0; for(ll l=3,r;l<=n&&l<=k;l=r+1){ r=min( n/(n/l),k); ans+= ( ((r-l+1)%mod) * ((n/l)%mod) ) %mod; ans%=mod; // cout<<l<<" "<<r<<" "<<ans<<endl; } return ans%mod; } int main(){ IOS ll n,k; cin>>n>>k; ll ans=0; if(k==1){ ans=n%mod; }else ans+=(k%mod+2*n%mod-2)%mod; //cout<<ans<<endl; ans+=diving(n,k)%mod+diving(n-1,k)%mod; cout<<ans%mod; return 0; }