又是一道周老师给的比赛的第一题。。。。。我似乎只适合做第一题
不过似乎有一个很痛的领悟,接下去再说吧
题目
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); //不要嫌麻烦不关文件。。会死的
啊多么痛的领悟----
不要用电脑管家啊!!!!
这是开着电脑管家的效果
只要关掉电脑管家,一切就好了
。。。这何尝不是一种领悟。。。
【谨记】
另外发现一个错误,要记得关文件,不要懒啊,懒会害死人的。。。