在 1 ≤ n ≤ N , 1 ≤ k ≤ K 1\leq n \leq N,1\le k\le K 1≤n≤N,1≤k≤K范围内,有多少对 ( n , k ) (n,k) (n,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=1∑Kn=1∑N(n%k==1∣∣n%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=1∑Kkn+k=2∑K(kn−1+1)
( + 1 +1 +1是因为 n − 1 k \frac{n-1}{k} kn−1里没有计算 n = 1 , n % k = 1 n=1,n\%k=1 n=1,n%k=1的情况)
显然,数论分块。
#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
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 K−1,这是 n = 1 n=1 n=1时一定成立, − 1 -1 −1是因为 ( 1 , 1 ) (1,1) (1,1)已经被计算过了。