您的位置:首页 > 其它

ssl1127-方程的解数【HASH,dfs】

2018-03-01 20:58 375 查看

前言

我只是凑数的。

正题



输入输出(建议无视)

Input

  第1行包含一个整数n。第2行包含一个整数M。第3行到第n+2行,每行包含两个整数,分别表示ki和pi。两个整数之间用一个空格隔开。第3行的数据对应i=1,第n+2行的数据对应i=n。

Output

仅一行,包含一个整数,表示方程的整数解的个数。

Sample Input

3

150

1 2

-1 2

1 2

Sample Output

178

解题思路

听真正的dalao讲的@神奇幂伟,大概就是把方程分成两半,如:

k1xp11+k2xp22=−k3xp33−k4xp44k1x1p1+k2x2p2=−k3x3p3−k4x4p4

然后用深搜前半段找出第一个的所有答案存进哈希表里(并且记录出现次数),然后再搜一次后半段寻找与前半段答案相反的话就算上方案

代码

#include<cstdio>
using namespace std;
const int maxn=4000037;//哈希个数
int n,m,hash[maxn],mid,a[7],p[7],num[maxn],S,ans;
int abs(int x)
{
if (x<0) return -x;
else return x;
}//绝对值,定位时使用
int hashmath(int x)
{return abs(x)%maxn;}//哈希函数
int locate(int x)//定位用
{
int i=0,w=hashmath(x);//哈希函数
while (i<maxn && hash[(w+i)%maxn]!=0 && hash[(w+i)%maxn]!=x)
i++;//找到位置
return (w+i)%maxn;//返回位置
}
void ins(int x)//加入
{
int w=locate(x);//定位
hash[w]=x;//改变值
num[w]++;//记录出现次数
}
bool find(int x)//查找
{
int w=locate(x);//位置
if (hash[w]==x) return true;//返回
else return false;
}
void dfs(int dep,int sum)//第一次搜
{
if (dep>=mid+1)
{
ins(sum);//插入
return;
}
for (int i=1;i<=m;i++)
{
ans=i;
for (int j=2;j<=p[dep];j++) ans*=i;//即使x^p
ans*=a[dep];//得出结果
dfs(dep+1,sum+ans);//搜
}
}
void dfs2(int dep,int sum)
{
if (dep>=n+1)
{
if (find(-sum)) S+=num[locate(-sum)];
//如果找到就记录
return;
}
for (int i=1;i<=m;i++)
{
ans=i;
for (int j=2;j<=p[dep];j++) ans*=i;
ans*=a[dep];
dfs2(dep+1,sum+ans);
}
}
int main()
{
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++)
{
scanf("%d%d",&a[i],&p[i]);
}
mid=n/2;//分成两段
dfs(1,0);
dfs2(mid+1,0);
printf("%d",S);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: