POJ P1186 方程的解数

来源:互联网 发布:洛阳网站建设启辰网络 编辑:程序博客网 时间:2024/05/22 04:30

题目大意:
这里写图片描述

题解:
hash:
我们发现,这题就是枚举答案,不过强行枚举全部,就为O(M^6),M最大为150,会超时,这时候我们折半枚举,把前一半全部的可能性全部求出然后塞进hash表中,然后枚举后一半的时候,每次找到一个可能性,就在hash表中找它的相反数,然后累加,注意hash表中还要有一个记录出现次数。
然后因为最大是maxlongint,所以我们预处理出1~M的在maxlongint以内的所有开方。
注意插入hash中的数可能是0,所以我们用当前hash表的位置表示的数的出现次数是否为0去找,不要用hash表中插入的数去找。
时间复杂度应该是O(2*M^3)

const     modn=4000037;var     hash:array [0..modn,1..2] of longint;     a:array [0..151,0..31] of longint;     k,p:array [0..7] of longint;     ans,i,j,n,m:longint;function locate(t:longint):longint;var     i:longint;begin     i:=abs(t) mod modn;     while (hash[i,2]<>0) and (hash[i,1]<>t) do     begin          inc(i);          if i>modn then i:=0;     end;     exit(i);end;procedure dfs(dep,sum:longint);var     i,j:longint;begin     if dep>n div 2        then begin                 j:=locate(sum);                 hash[j,1]:=sum;                 inc(hash[j,2]);             end        else for i:=1 to m do                 dfs(dep+1,sum+k[dep]*a[i,p[dep]]);end;procedure find(dep,sum:longint);var     i:longint;begin     if dep>n        then ans:=ans+hash[locate(-sum),2]        else for i:=1 to m do                 find(dep+1,sum+k[dep]*a[i,p[dep]]);end;begin     readln(n);     readln(m);     for i:=1 to n do         readln(k[i],p[i]);     if n=1 then     begin         if k[1]=0 then writeln(m)                   else writeln(0);         halt;     end;     for i:=1 to 30 do a[1,i]:=1;     for i:=2 to m do     begin           a[i,1]:=i;           for j:=2 to trunc(ln(maxlongint)/ln(i)) do               a[i,j]:=a[i,j-1]*i;     end;     dfs(1,0);     find(n div 2+1,0);     writeln(ans);end.
原创粉丝点击