又是一道周老师给的比赛的第一题。。。。。我似乎只适合做第一题

不过似乎有一个很痛的领悟,接下去再说吧

题目

1.hash函数(hash.pas/c/cpp)

【问题描述】

    明明觉得hash是个好算法,代码短、效率高。某天,他碰到了一个求正方形个数的问题,于是很淡定地枚举对角线,然后用hash判存在,妥妥的搞定,但是提交后却wa了几个点。仔细观察其hash函数为:h=x*y+x+y。为了让明明知道这个函数存在什么问题,对于给出一个h值,请你来告诉他有多少对(x,y)满足上述式子(max(x,y)≤h;h,x,y都为非负整数)?

【输入格式】

    多组测试数据,第一行为测试点的个数T,接下来每一行一个整数h,意义如上。

【输出格式】

    一共T行,每行一个整数,分别表示有多少组(x,y)满足要其对应的h值。

【数据范围】

    对于30%数据,h≤20,000,T≤1000;

    对于l00%数据,h≤100,000,000,T≤10000。  

【输入样例】

3

1

3

4

【输出样例】

2

3

2

【样例解释】

(1,0),(0,1)

(0,3),(1,1),(3,0)

(4,0),(0,4)

【分析】

【我的分析】

我们可以得到的规律是:
  i递增,j不变
  如:n=8 i=2 j=2
      n=11 i=3 j=2
      n=14 i=4 j=2
      ……
  i最小等于j,但是可以大于j
  然而第一个出现的位置是哪儿呢,其实就是((i(或j)+1)^2)-1
  任意两个n之间的差即为j+1
  ……

【正常分析】

暴力。。。。。。

【std分析】

  显然,对于h=x*y+x+y这个式子可以变换成h+1=(x+1)*(y+1)。

  令s=h+1,a=x+1,b=y+1:

  于是题目就变成了:对于式子s=a*b有多少组(a,b)满足要求。

    这个时候只要对s进行质因数分解,然后统计每个质因子的个数,答案就出来了:ans=ans+(fill[i]+1);(fill[i]为分解后第i个质因子的个数)

    最后一个要注意的地方:分解质因数。的过程中,可能最后会剩下一个很大的质因数,超过了预处理出的素数上限。这时只需要特判一下分解完后,s是否等于1,不是的话将答案*2就行了。

【代码】

#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<cmath> 
using namespace std;
int main()
{
    freopen("hash.in","r",stdin);
    freopen("hash.out","w",stdout);
    int n,i,j,p,q;
    cin>>p;
    for (q=1;q<=p;q++)
    {
     cin>>n;
    int t=int(sqrt(n));
    int ans=0;
    for (j=0;j<=t;j++)
     {
          int a=(j+1)*(j+1)-1;
if (a>n) { break; }
int b=n-a;
          if ((b%(j+1))==0) 
          {
                i=b/(j+1)+j;  //(不是+1,死了多少遍都不知道,太弱了)
                if ((i>=0) && (j>=0))
                 {
                        if (i==j) {ans++;}else{ans+=2;} 
                 } 
          }
     }
     cout<<ans<<endl;
    }
     return 0;
   fclose(stdin);
   fclose(stdout); //不要嫌麻烦不关文件。。会死的

啊多么痛的领悟----

不要用电脑管家啊!!!!

这是开着电脑管家的效果

 

 

只要关掉电脑管家,一切就好了

 

。。。这何尝不是一种领悟。。。

 

【谨记】

另外发现一个错误,要记得关文件,不要懒啊,懒会害死人的。。。

 

 

posted on 2014-07-09 22:13  seekdreamer  阅读(282)  评论(0编辑  收藏  举报