【noi2001】方程的解数

来源:互联网 发布:2016年速卖通销售数据 编辑:程序博客网 时间:2024/05/21 16:56

题目描述 Description
已知一个n元高次方程:

k1x1p1+k2x2p2+……+knxnpn = 0

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

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

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

输出描述 Output Description
文件仅一行,包含一个整数,表示方程的整数解的个数。

样例输入 Sample Input
3

150

1 2

-1 2

1 2

样例输出 Sample Output
178

数据范围及提示 Data Size & Hint
1≤n≤6;1≤M≤150;

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

方程的整数解的个数小于231。

★本题中,指数Pi(i=1,2,……,n)均为正整数。

/*审题:n元不是一元 相当于从m行n列的数中每一列取一个数,使其和为0 这不和上一个题一样吗。。 */#include<cstdio>#include<cstring>#include<algorithm>using namespace std;int n,m,k[10],p[10];int a[3375000],s1[3375000],s2[3375000],tot1,tot2;int poww(int n,int x){    int tmp=n;    for (int i=2; i<=x; i++)        n*=tmp;    return n;}void work(int t,int type){    if (type==1)    {        tot1++;        for (int i=1; i<=t; i++)            s1[tot1]+=k[i]*poww(a[i],p[i]);    }    else    {        tot2++;        for (int i=n/2+1; i<=n; i++)            s2[tot2]+=k[i]*poww(a[i-n/2],p[i]);    }}void dfs(int num,int t,int type){    if (num==t+1) {work(t,type); return;}    for (int i=1; i<=m; i++)    {        a[num]=i;        dfs(num+1,t,type);    }}int main(){    int ans=0;    scanf("%d%d",&n,&m);    for (int i=1; i<=n; i++) scanf("%d%d",&k[i],&p[i]);    dfs(1,n/2,1);    dfs(1,n-n/2,2);    sort(s1+1,s1+1+tot1);    sort(s2+1,s2+1+tot2);    int r=tot2;    for (int i=1; i<=tot1; i++)    {        while (r>=1&&s1[i]+s2[r]>0)            r--;        if (r<=0) break;        if (s1[i]+s2[r]!=0) continue;        int tmp=r;        while (r>=1&&s1[i]+s2[tmp]==0)        {            ans++; tmp--;        }    }    printf("%d",ans);    return 0;}
原创粉丝点击