牛客网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≤K1 \le n \le N, 1 \le k \le K1nN,1kK.

In order to avoid calculations of huge integers, report the answer modulo 109+710^9+7109+7 instead.

输入描述:

The input contains two integers N and K, 1N,K1e12.

输出描述:

Output the answer modulo  1e9+7

充分性简要证明 :

  • 我们可以认为 (n, k) 是一个 Legned Tuple 当且仅当可以通过将 n 通过减 k 和 除以 k 两种操作变为 1
  • 若 n 是 k 的倍数, 设 n=xk, 我们可以先执行 (x-1) 次 减 k 操作, 使得 n 变成 xk-(x-1)k=k, 最后执行 一次除以 k 操作即可
  • 若 n – 1 是 k 的倍数, 设 n=xk+1, 那么执行 x 次除以 k 操作即可

然后在时间复杂度O(n)的基础上压一压即可。

代码:

 

#include<bits/stdc++.h>
using namespace std;
long long n,k,f;
long long num,t;
long long ans,sum;
long long mod=1e9+7;
int main()
{
    cin>>n>>k;
    ans=k;
    ans+=n-1;
    ans%=mod;
    for(long long i=2; i<=min(n,k); i=sum+1)
    {
        sum=n/(n/i);
        sum=min(sum,k);
        sum=min(sum,n);
        ans+=(n/i)%mod*((sum-i+1)%mod)%mod;
        ans%=mod;
    }
    n--;
    for(long long i=2; i<=min(n,k); i=sum+1)
    {
        sum=n/(n/i);
        sum=min(sum,k);
        sum=min(sum,n);
        ans+=(((n/i)%mod)*((sum-i+1)%mod))%mod;
        ans%=mod;
    }
    cout<<ans%mod<<endl;
}
View Code

 

posted @ 2020-08-02 20:06  mdID(WWWZZZQQQ)  阅读(329)  评论(0)    收藏  举报