方程的解数(meet in the middle)

Posted zubizakeli

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了方程的解数(meet in the middle)相关的知识,希望对你有一定的参考价值。

  题目链接:http://cogs.pro:8080/cogs/problem/problem.php?pid=304

 

  题解:

  直接搜索(枚举)复杂度为O(m^n),可以用meet in the middle降为(sqrt(m^n))。

     什么是meet in the middle呢?

  就是把整个搜索范围分成两部分分开搜索。

  就这道题而言,我们把他分成两部分之后,可以算出每个部分的可能取值集合,然后再统计从两个集合中各取一个且和为0的方案数即可。

 

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #define LL long long
 6 #define RI register int
 7 using namespace std;
 8 const int INF = 0x7ffffff ;
 9 const int N = 10 ;
10 const int M = 3500000 ;
11 
12 inline int read() {
13     int k = 0 , f = 1 ; char c = getchar() ;
14     for( ; !isdigit(c) ; c = getchar())
15       if(c == -) f = -1 ;
16     for( ; isdigit(c) ; c = getchar())
17       k = k*10 + c-0 ;
18     return k*f ;
19 }
20 int n, m, rk1, rk2, lv, ans ; int p[N], k[N], p1[N], k1[N], res1[M], res2[M] ;
21 
22 inline int poww(int a,int b) {
23     int base = a, rres = 1 ;
24     while(b) {
25         if(b&1) rres *= base ;
26         base *= base ; b >>= 1 ;
27     }
28     return rres ;
29 }
30 void dfs(int now,int res,int *a,int &rk) {
31     if(now > lv) {
32         a[++rk] = res ; return ;
33     }
34     for(int i=1;i<=m;i++) {
35 //        printf("xxx\n") ;
36         dfs(now+1,res+k1[now]*poww(i,p1[now]),a,rk) ;
37     }
38 }
39 inline void work() {
40     int j = rk2 ;
41     sort(res1+1,res1+rk1+1) ; sort(res2+1,res2+rk2+1) ;
42     for(int i=1;i<=rk1;i++) {
43         while(res1[i]+res2[j] > 0 && j) j-- ;
44         if(j <= 0) break ;
45         if(res1[i]+res2[j] < 0) continue ;
46         int cnt1 = 1, cnt2 = 1 ;
47         while(res1[i] == res1[i+1] && i < rk1) i++, cnt1++ ;
48         while(res2[j] == res2[j-1] && j > 1) j--, cnt2++ ;
49         ans += cnt1*cnt2 ;
50     }
51 }
52 
53 int main() {
54 //    freopen("equation1.in","r",stdin) ;
55 //    freopen("equation1.out","w",stdout) ;
56     n = read(), m = read() ;
57     for(int i=1;i<=n;i++) {
58         k[i] = read(), p[i] = read() ;
59     }
60     lv = n>>1 ;
61     for(int i=1;i<=lv;i++) k1[i] = k[i], p1[i] = p[i] ;
62     dfs(1,0,res1,rk1) ;
63     for(int i=1;i<=n-lv;i++) k1[i] = k[i+lv], p1[i] = p[i+lv] ;
64     lv = (n+1)>>1 ;
65     dfs(1,0,res2,rk2) ;
66     work() ;
67     printf("%d",ans) ;
68     return 0 ;
69 }

 

以上是关于方程的解数(meet in the middle)的主要内容,如果未能解决你的问题,请参考以下文章

meet-in-the-middle 基础算法(优化dfs)

SPOJ4580 ABCDEF(meet in the middle)

折半搜索(meet in the middle)

跳房子——meet in the middle

E. XOR Guessing(Meet in the Middle)

子集(状态压缩)(meet in the middle)