第一届ACM金牌训练营网络测试赛 C. Math(简单数学)

Description

对于一个数对 (a,b),如果满足 a%b=a/b,则称这个数对为“好的数对”。如果 an,bn a ≤ n , b ≤ n , 那么有多少对数对是“好的数对”呢?

Input

多组数据。
每组数据一行,一个数表示n( 1n1e9 1 ≤ n ≤ 1 e 9 )。
数据组数不超过100。

Output

对于每组数据输出一行,表示“好的数对”的个数。

测试数据

Input

5
8
3
65
498
513
115
10
80
100

Output

3
7
1
131
1556
1611
268
10
172
227

解题思路

因为 a%b=a/b 且 a=a/b*b+a%b,所以 a=a%b*b+a%b=a%b*(b+1)
即 a=(a%b)*(b+1) ①
令a%b=t ②
则有: (b+1)*t n ③
    t < b ④
由③可得: bnt1 b ≤ n t − 1
结合④有: t<bnt1 t < b ≤ n t − 1 所以 tnt2 t ≤ n t − 2 化简可得 t(t+2)n t ∗ ( t + 2 ) ≤ n
所以枚举 t 在 sqrt(n)的时间复杂度内即可求解。
对于每一个t,对应的解的个数求解思路为:
由①②可得 a=t*(b+1) 由④可知 bmin=t+1 b m i n = t + 1 所以 amin=t(t+2) a m i n = t ∗ ( t + 2 )
对于当前遍历到的t而言,符合条件的a的取值范围是 [t*(t+2),n],又因为b+1->a+t,所以符合条件的取值个数为 nt(t+2)t+1 n − t ∗ ( t + 2 ) t + 1
最终结果随着t的遍历累加即可。

代码实现

#include
using namespace std;
typedef long long ll;
int main()
{
    ll n;
    while(~scanf("%lld",&n))
    {
        ll ans=0;
        ll t;
        for(t=1;t*(t+2)<=n;t++)
            ans+=(n-t*(t+2))/t+1;
        printf("%lld\n",ans);
    }
    return 0;
}

你可能感兴趣的:(简单数学,网络赛)