您的位置:首页 > 其它

折半搜索+hash——CODEVS1735 [NOI2001]方程的解数

2017-03-28 14:58 519 查看
NOI2001的题可以搜索A掉啊

http://codevs.cn/problem/1735/

看到数据有点萎。。。因为暴搜的时间复杂度150^6

那么试试折半搜索???

我们把全部数折半(前n/2个和后n/2个)然后分别暴搜

前半部分的答案可以保存在hash表中,方便与后半部分合并

时间复杂度完美优化到150^3

然后hash的模数再好好注意一下

然后就结束了

#include<bits/stdc++.h>
using namespace std;
const int MOD=5000017;
int ha[5000027]={0},sum[5000027]={0},mi[151][151];
int n,m,k[1001],p[1001],ans=0;
inline int hash(int p){
int w=abs(p)%MOD;
while(sum[w]&&ha[w]!=p){w++;if(w==MOD)w=0;}
return w;
}
inline void dfs(int x,int s){
if(x==n/2+1){
int p=hash(s);ha[p]=s;
sum[p]++;return;
}
for(int i=1;i<=m;i++)dfs(x+1,s+k[x]*mi[i][p[x]]);
}
inline void dfss(int x,int s){
if(x==n+1){
int p=hash(s);
ans+=sum[p];return;
}
for(int i=1;i<=m;i++)dfss(x+1,s-k[x]*mi[i][p[x]]);
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++){mi[i][0]=1;
for(int j=1;j<=150;j++)mi[i][j]=mi[i][j-1]*i;}
for(int i=1;i<=n;i++)scanf("%d%d",&k[i],&p[i]);
dfs(1,0);
dfss(n/2+1,0);
printf("%d",ans);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  搜索 hash