2020牛客多校第七场H题Dividing(整除分块)

链接: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;
}

 

posted @ 2020-08-02 13:44  杰瑞与汤姆  阅读(242)  评论(0编辑  收藏  举报