zoukankan      html  css  js  c++  java
  • 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;
    }

     

    细雨斜风作晓寒。淡烟疏柳媚晴滩。入淮清洛渐漫漫。 雪沫乳花浮午盏,蓼茸蒿笋试春盘。人间有味是清欢。
  • 相关阅读:
    LeetCode344
    LeetCode18四数之和扩展N数之和
    LeetCode383赎金信
    2018-2020创业总结
    LeetCode454四数相加
    普通dll项目添加WPF的Window对象
    WPF中RadioButton的数据绑定
    02 C# 文件压缩与解压
    WPF 使用附加属性声明 ICommand
    自定义WPF分页控件
  • 原文地址:https://www.cnblogs.com/cangT-Tlan/p/7517427.html
Copyright © 2011-2022 走看看