nyoj 136

题意:
描述

有以下等式:a1*x13+a2*x23+a3*x33+a4*x43+a5*x53=0

x1,x2,x3,x4,x5都就在区间[-50,50]之间的整数,且x1,x2,x3,x4,x5都不等于0.

问:给定a1,a2,a3,a4,a5的情况下,x1,x2,x3,x4,x5共有多少种可能的取值?

输入
第一行输入一个整数T(T<=10)表示测试数据的组数。
每组测试数据都只有一行,是5个整数,分表表示a1,a2,a3,a4,a5。(a1,a2,a3,a4,a5都在区间[-50,50]之间)
输出
对于每组数据输出一行,表示x1,x2,x3,x4,x5可能的取值种数
样例输入
1
37 29 41 43 47
样例输出
654

该问题不容易想到利用hash表,问题只要求解的个数,即(多少个x1-----x5)的组合,可以先把x1---x2的所有可能解写入hash表,然后在三重循环查找,注意找到了还要继续,记录个数。注意,可能会出现输入5个0的情况,该情况会导致超时(所有的0挂在一条链上),所有需要出掉重复的数字,在记录该数字出现的次数。

#include<stdio.h>
#include<string.h>
int H[300007];
struct con
{
	int value;
	int next;
	int count;	
}v[10010];
int main()
{
	int T=300007;
	int i,j,k,n,m,pos,next,hash,s,j_next;
	long long cnt;
	int a1,a2,a3,a4,a5;
	scanf("%d",&n);
	while(n--)
	{
		scanf("%d%d%d%d%d",&a1,&a2,&a3,&a4,&a5);
		pos=0;
		cnt=0;
		memset(H,-1,sizeof(H));
		memset(v,-1,sizeof(v));
		for(i=-50;i<=50;i++)
		{
			if(i==0)
			continue;
			for(j=-50;j<=50;j++)
			{
				if(j==0)
				continue;
				hash=s=-(i*i*i*a1+a2*j*j*j);
				if(hash<0)
				hash*=-103;
				hash%=T;
				j_next=H[hash];
				while(j_next!=-1)
				{
					if(v[j_next].value==s)
					{
						v[j_next].count++;
						break;
					}
					j_next=v[j_next].next;
				}
				if(j_next!=-1)
				continue;
				v[pos].value=s;
				v[pos].count=1;
				v[pos++].next=H[hash];
				H[hash]=pos-1;
			}
		}
		for(i=-50;i<=50;i++)
		{
			if(i==0)
			continue;
			for(j=-50;j<=50;j++)
			{
				if(j==0)
				continue;
				for(k=-50;k<=50;k++)
				{
					if(k==0)
					continue;
					s=hash=i*i*i*a3+j*j*j*a4+k*k*k*a5;
					if(hash<0)
					hash*=-103;
					hash%=T;
					next=H[hash];
					while(next!=-1)
					{
						if(v[next].value==s)
						{
							cnt+=v[next].count;
							break;	
						}
						next=v[next].next;
					}
					
				}
			}
		}
		printf("%I64d\n",cnt);
	}
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值