2020牛客多校第七场H-Dividing

题意:

1 ≤ n ≤ N , 1 ≤ k ≤ K 1\leq n \leq N,1\le k\le K 1nN,1kK范围内,有多少对 ( n , k ) (n,k) (n,k)传奇对。传奇对的条件是:

  1. ( 1 , k ) (1,k) (1,k)一定是传奇对;
  2. ( n , k ) (n,k) (n,k)是传奇对, ( n + k , k ) (n+k,k) (n+k,k) ( n k , k ) (nk,k) (nk,k)都是传奇对。

题解:

从题意可以看出,应该固定 k k k,分析 n n n。对于任意一个k,我们来看满足条件的 n n n

首先, n = 1 n=1 n=1的时候是传递对,那么在乘 n n n和加 n n n后, n = k , n = k + 1 n=k,n=k+1 n=k,n=k+1都是传奇对。不论是乘 n n n还是加 n n n,不改变 n % k n\%k n%k的值,始终 n % k = 0 n\%k=0 n%k=0或者 n % k = 1 n\%k=1 n%k=1

那么也就是计算
∑ k = 1 K ∑ n = 1 N ( n % k = = 1 ∣ ∣ n % k = = 0 ) \sum_{k=1}^{K}\sum_{n=1}^{N}(n\%k==1||n\%k==0) k=1Kn=1N(n%k==1n%k==0)
转换一下
∑ k = 1 K n k + ∑ k = 2 K ( n − 1 k + 1 ) \sum_{k=1}^{K} \frac{n}{k}+\sum_{k=2}^{K}( \frac{n-1}{k}+1) k=1Kkn+k=2K(kn1+1)
( + 1 +1 +1是因为 n − 1 k \frac{n-1}{k} kn1里没有计算 n = 1 , n % k = 1 n=1,n\%k=1 n=1,n%k=1的情况)

显然,数论分块。

AC代码:

#include 
#define pb push_back 
#define fir first
#define sec second
#define ms(a,b) memset(a,b,sizeof(a)) 
#define INF 0x3f3f3f3f
#define sp system("pause")
#define multi int T;scanf("%d",&T);while(T--) 
using namespace std;
typedef long long ll;
typedef double db;
const int N=1e4+5;
const int mod=1e9+7;
const db pi=acos(-1.0);
int main()
{
    #ifndef ONLINE_JUDGE
    freopen("D:\\work\\data.in","r",stdin);
    #endif
    ll N,K,ans=0;
    scanf("%lld%lld",&N,&K);
    for(ll l=1,r,p;l<=min(N,K);l=r+1){
        p=N/l;
        r=min(K,N/p);
        ll tmp=(r-l+1)%mod*p%mod;
        ans=(ans+tmp)%mod;
    }
    N--;
    for(ll l=2,r,p;l<=min(N,K);l=r+1){
        p=N/l;
        r=min(K,N/p);
        ll tmp=(r-l+1)%mod*p%mod;
        ans=(ans+tmp)%mod;
    }
    ans=(ans+K-1)%mod;
    printf("%lld\n",ans);
}

1、 循环终止条件记得加min,否则n p = n k = 0 p=\frac{n}{k}=0 p=kn=0 n 0 \frac{n}{0} 0n会RE。

2、r记得加min,否则会超出范围

3、第二个循环 l l l是从2开始的, k = 1 k=1 k=1时不存在 n % k = 1 n\%k=1 n%k=1

4、最后结果加上 K − 1 K-1 K1,这是 n = 1 n=1 n=1时一定成立, − 1 -1 1是因为 ( 1 , 1 ) (1,1) (1,1)已经被计算过了。

你可能感兴趣的:(数学)