SSL

xiaoxiao2021-02-28  28

题意:

    

思路:

    我们可以把这个方程一半的加数移到右边去,例k1x1p1+k2x2p2+k3x3p3=0移项变成k1x1p1+k2x2p2=-k3x3p3可以减少我们枚举x的次数,用哈希表存左边求出的情况有哪些,在右边枚举的时候我们就可以判断是否和左边相等,然后加上次数就可以了。

代码:

#include<cstdio> #define maxn 4000003 using namespace std; int z,a[maxn][2],n,k[7],p[7],m,ans; int ksm(int x,int y)//快速幂 { int s=1; while (y>0) { if (y%2!=0) s*=x; x*=x; y/=2; } return s; } int hash(int x) { if (x<0) x=x*-1; return x%maxn; } int locate(int x) { int i=0,w=hash(x); while (i<maxn&&a[(i+w)%maxn][0]!=0&&a[(i+w)%maxn][0]!=x) i++; return (i+w)%maxn; } void insert(int x) { int z=locate(x); a[z][0]=x; a[z][1]++;//a[][1]存左边求出的结果的次数 } void dfs(int x,int sum) { if (x==n/2) for (int i=1;i<=m;i++) insert(sum+k[x]*ksm(i,p[x]));//把我们求出的情况加到哈希表里去 else for (int i=1;i<=m;i++) dfs(x+1,sum+k[x]*ksm(i,p[x]));//继续枚举x return; } void bfs(int x,int sum) { int t; if (x==n) for (int i=1;i<=m;i++) { t=-1*(sum+k[x]*ksm(i,p[x]));//因为右边的是移项了的,所以要变号 if (a[locate(t)][0]==t) ans+=a[locate(t)][1];//加上出现次数 } else for (int i=1;i<=m;i++) bfs(x+1,sum+k[x]*ksm(i,p[x]));//枚举x return; } int main() { scanf("%d%d",&n,&m); for (int i=1;i<=n;i++) scanf("%d%d",&k[i],&p[i]); if (n==1)//这里是特殊情况 { if (k[1]==0) printf("%d",m); else printf("0"); return 0; } dfs(1,0);//求左边的 bfs(n/2+1,0);//把这个方程分成两段求,这里求右边 printf("%d",ans); }
转载请注明原文地址: https://www.6miu.com/read-2626686.html

最新回复(0)