zoukankan      html  css  js  c++  java
  • 【中等难度】hash函数

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

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

    题目

    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); //不要嫌麻烦不关文件。。会死的

    啊多么痛的领悟----

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

    这是开着电脑管家的效果

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

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

    【谨记】

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

    noip忘记取模的痛
  • 相关阅读:
    字符的编码
    数据的基本类型和内置方法(二)
    基本的数据类型和内置方法介绍 (一)
    流程运算 if while for
    用户交换 基本数据类型 基本运算符 格式化输出
    机器语言发展简介和变量的介绍
    计算机基础
    Python学习建议和要求总结
    CH135 最大子序和 题解报告
    HRBUST1356 Leyni,罗莉和队列 题解报告
  • 原文地址:https://www.cnblogs.com/seekdreamer/p/3834657.html
Copyright © 2011-2022 走看看