2020牛客多校第七场 Dividing

题意
( n , k ) A n 1 N k 1 K ? 给出(n,k)是A的要求,问n属于1到N以及k属于1到K中\\有多少种组合?
思路
k , k ( 1 , k ) > ( 1 + k , k ) > ( 1 + 2 k , k ) . . . > ( 1 + x k , k ) x ( 1 , k ) > ( k , k ) > ( ) > ( 2 k , k ) > . . . > ( x k , k ) x 思路是队友想出来的,现在回头看这题,确实也是比较显然的\\对于每一个k,我们考虑由这个k可以拓展的所有组合\\(1,k)->(1+k,k)->(1+2k,k)...->(1+xk,k)\\其中x为非负整数\\(1,k)->(k,k)->(加法)->(2k,k)->...->(xk,k)\\其中x为正整数
问题转化(注意/表示下取整)
k = 1 k = K ( N / k ) + k = 1 k = K ( N / k ) + K N 求解\sum_{k=1}^{k=K}(N/k)+\sum_{k=1}^{k=K}(N/k)+K-N
1 < = x 1 k < = N 1 < = x 2 k + 1 < = N , x 1 k x 2 k 解释:1<=x_1k<=N以及1<=x_2k+1<=N,求所有\\x_1k以及x_2k去重后的个数
x 1 k N / k x 2 k 0 < = x 2 k < = N 1 1 + ( N 1 ) / k 先不考虑去重\\算x_1k的个数,简单直接N/k\\算x_2k的个数,化简0<=x_2k<=N-1,因此数目等于\\1+(N-1)/k
= k = 1 k = K ( N / k ) + k = 1 k = K ( N / k ) + K 因此总数(未去重)=\sum_{k=1}^{k=K}(N/k)+\sum_{k=1}^{k=K}(N/k)+K
考虑重复情况
x k = y k + 1 ( x y ) k = 1 k = 1 k = 1 x k = x [ 1 , N ] x k + 1 = x + 1 [ 1 , N ] = N a n s = k = 1 k = K ( N / k ) + k = 1 k = K ( N / k ) + K N xk=yk+1即(x-y)k=1\\推出k=1时才可能有重复,所以对于k=1考虑,发现\\xk=x表示的范围为[1,N]\\xk+1=x+1表示的范围[1,N]\\推知重复数=N\\ans=\sum_{k=1}^{k=K}(N/k)+\sum_{k=1}^{k=K}(N/k)+K-N得证
如何计算呢?
k K N ! K > N N N / N = 0 考虑到k范围比较大,直接整除分块即可,套套板子就过了\\比赛时遇到一个笑话,K与N不相等可以直接套板子吗?\\可以呀!\\如果K>N,那么算到N肯定结束,因为N/比N大的数=0
K < N 如果K<N的话,直接截断。

#include <iostream>
#include <cstdio>
#include <cstdlib>
using namespace std;
const long long MOD = 1e9+7;
long long getans(long long K, long long N){
    long long ans = 0;
    for(long long l = 1, r ; l <= N; l = r+1){
        r = N/(N/l);
        r = min(r , K);
        ans = (ans + ((r-l+1) % MOD * (N/l) % MOD) % MOD)%MOD;
        if(r == K) break;
    }
    return ans;
}
long long K, N;
int main(){
    scanf("%lld %lld", &N, &K);
    long long ans = ((getans(K , N) + getans(K , N-1)) % MOD + K)%MOD;
    ans = ans - N;
    while(ans < 0)
        ans += MOD;
    ans %= MOD;
    printf("%lld\n", ans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_44412226/article/details/107736314