2020牛客多校第七场H题Dividing(整除分块)
链接:https://ac.nowcoder.com/acm/contest/5672/H
题目描述
The following rules define a kind of integer tuple - the 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.
- (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.
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))
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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; }
此题还有一个坑点 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; }