HNUST 1486: 小明的数学

来源:互联网 发布:java开发的开源框架 编辑:程序博客网 时间:2024/05/26 15:56

1486: 小明的数学

时间限制: 1 Sec  内存限制: 128 MB
提交: 101  解决: 22
[提交][状态][讨论版]

题目描述

给一个整数n,你能告诉我有多少种方式写成:n = i * j + i + j (0 < i <= j)

输入

第一行T(<2000).接下来T行,每行一个整数n.

输出

一行一个整数。

这题也算一个水题吧,找到了关键才能AC,可惜楼主也是交了五六次才AC了。。。

思路:上来首先吐槽一下出题者,不说n的范围。这题一开始我就找了一下规律,打了个表。规律显然,自己看图。

所以我就先写成矩阵模式,大家看的懂一些

3 5 7 9 11 13 15

5 8 11 14 17 20 23

7 11 15 19 23 27 31

....不想打字了,懒

显然每一行都是一个等差数列,并且首项也是等差的,这就好办了。我第一想法是看n是否在每一行中,复杂度O(n/2),华丽丽的TLE了,

后来我就改变了策略,先看主对角线(主对角线不懂得看看离散数学),他就是i==j构成的,简化就是i(i+2),如果在的话 ,sum++,在以对角线

后一元素为起点(首项),判断是否在这一行,这样递增的速度就大幅增加,不会超时了,然后就是等差数嘛,公式很好推,行数从一开始,每一行

首元素就是i(i+1)-1,公差就是i,我用LL 花了600ms,换了int好像200ms就AC了。。。上代码

#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<algorithm>#include<cmath>using namespace std;typedef long long LL;int main(){    int T,n,sum,k;    scanf("%lld",&T);    while(T--)    {        sum=0;        scanf("%d",&n);        k=floor(sqrt(n*1.0));        if(k*(k+2)==n) sum=1;        for(int i=2; n>=(i+1)*i-1; i++) ///for就是找右边的元素,是否在这一行        if((n-((i+1)*i-1))%i==0)  sum++;///刚开始我是吧它乘以2,因为i,j是对称的,上方有,下方就有        printf("%d\n",sum);             ///然后三次WA (⊙o⊙)…,后来一看题,i<=j。。。                                               ///所以就砍掉了一半数据,不用乘以2咯    }    return 0;}