• 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;
    }

     

    细雨斜风作晓寒。淡烟疏柳媚晴滩。入淮清洛渐漫漫。 雪沫乳花浮午盏,蓼茸蒿笋试春盘。人间有味是清欢。
  • 相关阅读:
    【WPF】绘制柱状图、折线图、扇形图
    【WPF】获取容器宽高
    【SQL】SQL Server、MySQL、SQLite获取自增ID、自增ID清零
    【SQL Server操作】SQL Server重命名数据库及解决数据库无法分离的问题
    【数据迁移】MySQL数据库迁移到SQL Server
    【MySQL操作】MySQL导入导出数据库
    【MySQL操作】MySQL Workbench远程连接的一些操作
    【c#】遍历获得一个类的所有属性名
    vue 跨域 springCloud @CrossOrigin注解
    解决IDEA右侧maven不显示方法
  • 原文地址:https://www.cnblogs.com/cangT-Tlan/p/7517427.html
Copyright © 2020-2023  润新知