cogs 304. [NOI2001] 方程的解数(meet in the middle)

304. [NOI2001] 方程的解数

★★☆   输入文件:equation1.in   输出文件:equation1.out   简单对比
时间限制:3 s   内存限制:64 MB

问题描述

已知一个n元高次方程:

Image:Equation1.gif

 

k1xp11+k2xp22++ knxpnn=0

 

其中:x1, x2, …,xn是未知数,k1,k2,…,kn是系数,p1,p2,…pn是指数。且方程中的所有数均为整数。

假设未知数1≤ xi ≤M, i=1,,,n,求这个方程的整数解的个数。

输入文件

文件的第1行包含一个整数n。第2行包含一个整数M。第3行到第n+2行,每行包含两个整数,分别表示ki和pi。两个整数之间用一个空格隔开。第3行的数据对应i=1,第n+2行的数据对应i=n。


输出文件

文件仅一行,包含一个整数,表示方程的整数解的个数。

输入样例

3
150
1 2
-1 2
1 2

输出样例

178


约束条件

1<=n<=6;1<=M<=150;

Image:Equation2.gif

 

|k1Mp1|+|k2Mp2|++|knMpn|<231

 

方程的整数解的个数小于2^31。

★本题中,指数Pi(i=1,2,……,n)均为正整数。
思路:meet in the middle。

计算满足 a+b+c+d+e+f=0  的数的个数

可以算 (a+b+c)+ (d+e+f) = 0

dfs两次,每次dfs一半

结果用双指针逼近法、乘法原理 O(n) 处理

dfs中 now代表计算到第几个数 ,tot代表当前的总和,tmp存储和是几,sum存储有几个和。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define MAXN 3442951
using namespace std;
int n,m,half,last,sum1,sum2,ans;
int k[10],p[10],tmp1[MAXN],tmp2[MAXN];
int fastpow(int a,int b){
    int s=1;
    while(b){
        if(b&1)    s=s*a;
        a=a*a;
        b>>=1;
    }
    return s;
}
void dfs(int now,int tot,int *tmp,int &sum){
    if(now>last){
        tmp[++sum]=tot;
        return ;
    }
    for(int i=1;i<=m;i++)
        dfs(now+1,tot+k[now]*fastpow(i,p[now]),tmp,sum);
}
void work(){
    int cnt1,cnt2,j=sum2;
    sort(tmp1+1,tmp1+1+sum1);
    sort(tmp2+1,tmp2+1+sum2);
    for(int i=1;i<=sum1;i++){
        while(j&&tmp1[i]+tmp2[j]>0)    j--;
        if(!j)    break;
        if(tmp1[i]+tmp2[j]==0){
            cnt1=cnt2=1;
            while(i<sum1&&tmp1[i]==tmp1[i+1])    cnt1++,i++;
            while(j>1&&tmp2[j]==tmp2[j-1])    cnt2++,j--;
            ans+=cnt1*cnt2;    
        }    
    }
}
int main(){
    freopen("equation1.in","r",stdin);
    freopen("equation1.out","w",stdout);
    scanf("%d%d",&n,&m);
    half=n/2;
    for(int i=1;i<=n;i++)
        scanf("%d%d",&k[i],&p[i]);
    last=half;
    dfs(1,0,tmp1,sum1);
    last=n;
    dfs(half+1,0,tmp2,sum2);
    work();
    cout<<ans;
}

 

 

posted @ 2017-09-13 19:55  一蓑烟雨任生平  阅读(202)  评论(0编辑  收藏  举报