Ice Rain(数论+思维)

Ice Rain

 Ice Rain------I was waiting for a girl, or waiting for been addicted to the bitter sea. Love for irrigation in silence. No one considered whether the flowers came out or wither. Love which I am not sure swing left and right. I had no choice but to put my sadness into my heart deeply.

   Yifenfei was waiting for a girl come out, but never.
His love is caught by Lemon Demon. So yifenfei ’s heart is “Da Xue Fen Fei” like his name.
The weather is cold. Ice as quickly as rain dropped. Lemon said to yifenfei, if he can solve his problem which is to calculate the value of , he will release his love.
Unluckily, yifenfei was bored with Number Theory problem, now you, with intelligent, please help him to find yifenfei’s First Love.

Input
Given two integers n, k(1 <= n, k <= 10 9).
Output
For each n and k, print Ice(n, k) in a single line.
Sample Input

5 4
5 3

Sample Output

5
7

题意:

让我们求 i = 1 n k % i

分析:

首先对于一个k%i的值我们可以根据

k = i × t + r

其中i是取模的数,t是商,r便是k%i这个余数

因此我们有

k   %   i = r = k i × t

所以

i = 1 n k % i = i = 1 n ( k i × t ) = k n i = 1 n i × k i

所以我们的问题转换成了求

i = 1 n i × k i = 1 × k 1 + 2 × k 2 + . . . + n × k n

根据向下取整,我们知道 k 1 k n 中一定可以分成一段一段连续的等值区间( k i k j ),当然了区间最小长度为1,也就是就一个这样的值(比如 4 3 = 1 , 4 4 = 1

对于某些区间来说区间长度可能很庞大,这样当我们碰到第一个i使得 k i = d 时,如果我们能得到区间的最后一个编号j( k j = d )那么我们就可以直接将d提出来,剩下的部分用等差数列求和公式算,大大增加了效率。

d = k i , j = k d 那么j就是我们要求的最后一个满足要求的位置
因此下次直接可以跳到j+1位置

证明:
已知 k i = d ,我们要求得一个j使得区间[i,j]之间的每个数 l k l = d
那么令 j = k d ,肯定可以使得区间[i,j]内的数满足性质,但是它是不是最后一个呢?
假设令 k j + 1 = d
d ( j + 1 ) k
根据 k d = j
可以得到 k ( d × j ) < d
k < d ( j + 1 )
矛盾,因此j是最大的

而且根据式子

i = 1 n i × k i = 1 × k 1 + 2 × k 2 + . . . + n × k n

我们可以知道当n>k之后就变成0了,所以我们只需要求出小于等于n的即可

code:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll n,k;
int main(){
    while(scanf("%lld%lld",&n,&k) != EOF){
        ll ans = n * k;
        if(n > k) n = k;
        for(ll i = 1; i <= n;){
            ll d = k / i;
            ll j = k / d;
            if(j > n) j = n;
            ans = ans - d * ((j - i + 1) * (i + j) / 2);//这里等比数列求和公式相当于a1 = i,通项是j,公比为1,个数j-i+1个
            i = j + 1;
        }
        printf("%lld\n",ans);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/codeswarrior/article/details/81362250
ice