题意:传送门
题解:因为直接从头暴搜是150^6,直接爆T,所以采取折半搜索,先搜前n/2个,然后用hash记录,之后再搜后n/2个,然后将答案的负数是否在哈希表中出现过,并加以统计答案,最后复杂度就降为150^3
附上代码:
#include<iostream>
#include<cstdio>
#define hash HHH
using namespace std;
inline int read()
{
char ch=getchar();
int f=1,x=0;
while(!(ch>='0'&&ch<='9')){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();}
return x*f;
}
const int mod=12313813;
struct data{int value,num;}hash[mod];
int n,m,k[10],p[10],pd[155][155],ans;
inline int HASH(int value)
{
int lc=int(abs(value))%mod;
while(hash[lc].num>0&&hash[lc].value!=value)lc=(lc+1)%mod;
return lc;
}
void pre()
{
for(int i=0;i<=150;i++){
pd[i][0]=1;
for(int j=1;j<=150;j++){
pd[i][j]=pd[i][j-1]*i;
}
}
}
void dfs1(int x,int value)
{
if(x>n/2){
int x=HASH(value);
hash[x].num++;
hash[x].value=value;
return ;
}
for(int i=1;i<=m;i++){
dfs1(x+1,value+k[x]*pd[i][p[x]]);
}
}
void dfs2(int x,int value)
{
if(x>n){
int x=HASH(value);
ans+=hash[x].num;
return ;
}
for(int i=1;i<=m;i++){
dfs2(x+1,value-k[x]*pd[i][p[x]]);
}
}
int main()
{
pre();
n=read();m=read();
for(int i=1;i<=n;i++)k[i]=read(),p[i]=read();
dfs1(1,0);
dfs2(n/2+1,0);
printf("%d\n",ans);
return 0;
}