牛客多校(2020第七场) H-Divding

题目描述
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 109+7instead.

输入描述:
The input contains two integers N and K,1≤N,K≤1012
输出描述:
Output the answer modulo 109+7
示例1
输入

3 3

输出

8

示例2
输入

3 9

输出

14

题解:

  思路:(n,k)是Legend Tuple的条件是,当且仅当满足下面三个要求中的某一个:

    • n ==  1
    • n是k的倍数
    • n-1是k的倍数      
  所以我们可以遍历k,对于每个k,用n/k计算出满足第二个条件的个数,用(n-1)/k求出满足第三个条件的个数,所以对于每个k,其实Legend Tuple的个数有 n/k + (n-1)/k
  又因为n, k非常的大,所以可以想到使用数论分块来实现(n/i + (n-1)/i) (i属于(1,k));

   关于数论分块:

    

 

 

     那么如何求每一块的左右边界?

 

      这里还要讲解一个知识点:给定正整数 i 和 n 满足 i <= n ,使得 n / i = n / x成立的最大 x = n / (n / i) (证明过程参考某乎)

 

      所以当左边界为 i 时,右边界为 n / (n / i)  

1 数论分块代码
2 ll ans=0;
3 for(ll l=1,r;l<=n;l=r+1)
4 {
5     r=n/(n/l);
6     ans+=(r-l+1)*(n/l);
7 }

 

所以类比,此题也得解,代码如下

 1 //数论分块
 2 #include<iostream>
 3 using namespace std;
 4 
 5 typedef long long ll;
 6 const ll M = 1e9 + 7;
 7 ll n, k;
 8 
 9 void solve() {
10     ll ans = (n % M + k % M - 1) % M; //因为任何(1,n),(n,1)属于Legend Tuple,又因为(1,1)重复,固然减去1
11     
12     //数论分块代码块
13 
14     //n = n
15     for (ll left = 2, right; left <= k; left = right + 1) {
16         ll x = n / left;
17         if (x == 0) break;
18         right = n / x;
19         ans = (ans + (x%M * (min(right, k) - left + 1) % M) % M) % M; //min(right, k)的意义在于,求左边界为i的右边界,i最大为k,固需要进行一次筛选
20     }
21 
22     //n = n-1
23     for (ll left = 2, right; left <= k; left = right + 1) {
24         ll x = (n-1) / left;
25         if (x == 0) break;
26         right = (n-1) / x;
27         ans = (ans + (x%M * (min(right, k) - left + 1) % M) % M) % M;
28     }
29     cout << ans << "\n";
30 }
31 
32 int main() {
33     cin >> n >> k;
34     solve();
35     return 0;
36 }

 

 参考数论分块讲解博客: https://blog.csdn.net/weixin_43785386/article/details/104410046?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522159634489919725247608893%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=159634489919725247608893&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_ecpm_v3~pc_rank_v2-5-104410046.first_rank_ecpm_v3_pc_rank_v2&utm_term=%E6%95%B0%E8%AE%BA%E5%88%86%E5%9D%97%E6%B1%82%E5%92%8C&spm=1018.2118.3001.4187

posted @ 2020-08-02 14:39  Mr__wei  阅读(30)  评论(0编辑  收藏  举报