#哈希,深搜#SSL 1127 方程的解数

本文介绍了一种使用深度优先搜索结合哈希表的方法来解决特定类型的方程问题。通过将问题分解为两部分并分别进行深搜,然后利用哈希表存储和查找结果,最终高效地找到了所有可能的解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目

这里写图片描述


分析

首先数据点很小,所以就用深搜,
k1x1p1+k2x2p2+……+k5x5p5+k6x6p6=0k1x1^{p1}+k2x2^{p2}+……+k5x5^{p5}+k6x6^{p6}=0k1x1p1+k2x2p2++k5x5p5+k6x6p6=0
k1x1p1+k2x2p2+k3x3p3=−k4x4p4−k5x5p5−k6x6p6k1x1^{p1}+k2x2^{p2}+k3x3^{p3}=-k4x4^{p4}-k5x5^{p5}-k6x6^{p6}k1x1p1+k2x2p2+k3x3p3=k4x4p4k5x5p5k6x6p6
用两个深搜
求出答案后哈希。


哈希代码

#include <cstdio>
#define mod 2600137
using namespace std;
int n,m,k[7],p[7],hash[mod+1],sum[mod+1],answer;
int pows(int x,int y){//快速幂
	int ans=1;
	while (y){
		if (y&1) ans*=x;
		x*=x; y>>=1;
	}
	return ans;
}
int abs(int x){return (x>0)?x:-x;}
int locate(int x){
	int orig=abs(x)%mod,i=0;
	while (i<mod&&hash[(orig+i)%mod]&&hash[(orig+i)%mod]!=x) i++;
	return (orig+i)%mod;
}
void insert(int x){
	int pos=locate(x);
	hash[pos]=x;
	sum[pos]++;
}
void dfs1(int dep,int s){
	if (dep>n/2) insert(s);//插入
	else for (int i=1;i<=m;i++) dfs1(dep+1,s+k[dep]*pows(i,p[dep]));
}
void dfs2(int dep,int s){
	if (dep>n) {
	int pos=locate(-s);
	if (hash[pos]==-s) answer+=sum[pos];//答案
	}
	else for (int i=1;i<=m;i++) dfs2(dep+1,s+k[dep]*pows(i,p[dep]));
}
int main(){
	scanf("%d%d",&n,&m);
	for (int i=1;i<=n;i++) scanf("%d%d",&k[i],&p[i]);
	dfs1(1,0); dfs2(n/2+1,0);
	printf("%d",answer);
	return 0;
}

当然快排+二分和双指针也会会给出来的


二分代码

#include <cstdio>
#include <algorithm>
using namespace std;
int n,m,k[7],p[7],a[3500001],n1,answer;
int pows(int x,int y){
	int ans=1;
	while (y){
		if (y&1) ans*=x;
		x*=x; y>>=1;
	}
	return ans;
}
int erfen(int l,int r,int x){
	int mid;
	while (l<=r){
		mid=(l+r)>>1;
		if (a[mid]>x) r=mid-1;
		else if (a[mid]<x) l=mid+1;
		else break;
	}
	if (a[mid]!=x) return 0;
	int head=mid,tail=mid;
	while (a[head]==x) head--; head++;//左右扩散
	while (a[tail]==x) tail++; tail--;
	return tail-head+1;
}
void dfs1(int dep,int s){
	if (dep>n/2) a[++n1]=s;
	else for (int i=1;i<=m;i++) dfs1(dep+1,s+k[dep]*pows(i,p[dep]));
}
void dfs2(int dep,int s){
	if (dep>n) answer+=erfen(1,n1,-s);
	else for (int i=1;i<=m;i++) dfs2(dep+1,s+k[dep]*pows(i,p[dep]));
}
int main(){
	scanf("%d%d",&n,&m);
	for (int i=1;i<=n;i++) scanf("%d%d",&k[i],&p[i]);
	dfs1(1,0); stable_sort(a+1,a+1+n1); //快排
	dfs2((n>>1)+1,0);
	printf("%d",answer);
	return 0;
}

#双指针

#include <cstdio>
#include <algorithm>
#define check1 if (head1>n1) break//越界
#define check2 if (head2>n2) break//越界
using namespace std;
int n,m,k[7],p[7],a[3500001],b[3500001],n1,n2,answer,big,sma=2147483647;
int pows(int x,int y){
	int ans=1;
	while (y){
		if (y&1) ans*=x;
		x*=x; y>>=1;
	}
	return ans;
}
void dfs1(int dep,int s){
	if (dep>n/2) {a[++n1]=s; big=max(big,s); sma=min(sma,s);}
	else for (int i=1;i<=m;i++) dfs1(dep+1,s+k[dep]*pows(i,p[dep]));
}
void dfs2(int dep,int s){
	if (dep>n) {if (big>=-s&&sma<=-s) b[++n2]=-s;}
	else for (int i=1;i<=m;i++) dfs2(dep+1,s+k[dep]*pows(i,p[dep]));
}
int main(){
	scanf("%d%d",&n,&m);
	for (int i=1;i<=n;i++) scanf("%d%d",&k[i],&p[i]);
	dfs1(1,0); dfs2(n/2+1,0);
	stable_sort(a+1,a+1+n1); stable_sort(b+1,b+1+n2);
    int head1=1,head2=1;
	while (true){
		int s=0;
		while (a[head1]<b[head2]) head1++; check1;//前面比后面小
		while (a[head1]>b[head2]) head2++; check2;//前面比后面大
		while (a[head1]==b[head2]) s++,head2++; head2--;//寻找区间
		while (a[head1]==b[head2]) head1++,answer+=s; check1; head2++; check2;//答案
	}
	printf("%d",answer);
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值