• SSLZYC 1127 方程的解数


    题目大意:
    这里写图片描述


    思路:
    肯定DFS!
    一开始想枚举每个x,但是看到数据范围O(n^6)。。。
    所以就想到了下面这种方法:

    利用等式的性质,将后n/2个数移到等号右边,就得到了:
    **k1x1^p1+k2x2^p2+k3x36^p3=-(k4x4^p4+k5x5^p5+k6x6^p6)**
    这样只需分别枚举两边,利用哈希表来判断是否相等即可。

    时间复杂度:O(n^3)


    代码:

    #include <iostream>
    #include <cstdio>
    #include <cmath>
    #include <algorithm>
    using namespace std;
    
    const int emm=48651279;  //初始化用的随机数,如果该数设的很大,则与答案“撞衫”的可能性就小。
    const int k=4000037;  //很大的数,在哈希函数中使用
    int num[k+10],ha[k+10],a[11],b[11];
    int n,m;
    long long sum;
    
    int h(int x)  //哈希函数
    {
        return x%k;
    }
    
    int ksm(int x,int y)  //快速幂
    {
        int ans=1;  //记录答案
        while(y>0)
        {
            if(y&1) ans*=x;
            x*=x;
            y/=2;
        }
        return ans;
    }
    
    
    int locate(int x)  //查找
    {
        int t=h(abs(x));  //使用哈希函数
        int i=0;
        while (i<k&&ha[(t+i)%k]!=x&&ha[(t+i)%k]!=emm) i++;  //直到找到一个空位或该数为止
        return (t+i)%k;
    }
    
    void insert(int x)  //插入数
    {
        int y=locate(x);
        if (ha[y]==emm) ha[y]=x;
        num[y]++;  //记录该数有几个
    }
    
    bool pos(int x)  //查找一个数
    {
        int y=locate(x);
        if (ha[y]!=emm) return true;
         else return false;
    }
    
    void dfs1(int x,int K)  //搜索前n/2个数
    {
        if (x==n/2+1)  //如果已经搜完了
        {
            insert(K);  //插入这些数的和
            return;  //返回
        }
        for (int i=1;i<=m;i++)  //枚举x
        {
            int s=ksm(i,b[x]);
            s*=a[x];
            dfs1(x+1,K+s);  //搜索
        }
    }
    
    void dfs2(int x,int K)  //搜索后n/2个数 
    {
        if (x==n+1)  //如果已经搜完了
        {
            if (pos(-K)==true) sum+=num[locate(-K)];  //查找是否在哈希表中
            return;  //返回
        }
        for (int i=1;i<=m;i++)  //枚举x 
        {
            int s=ksm(i,b[x]);
            s*=a[x];         
            dfs2(x+1,K+s);  //搜索
        }
    }
    
    int main()
    {
        scanf("%d%d",&n,&m);
        for (int i=1;i<=n;i++)
         scanf("%d%d",&a[i],&b[i]);  
        for (int i=1;i<=k+9;i++)
         ha[i]=emm;
        if (n==1)  //特判
        {
            if (a[1]==0) printf("%d\n",m);
            else printf("0");
            return 0;
        }
        dfs1(1,0);
        dfs2(n/2+1,0);  //搜索
        printf("%lld\n",sum);
        return 0;
    }
    
  • 相关阅读:
    用webservice实现的一个天气预报程序
    让VS.net2005手机模拟器上网
    EVC4.0 PPC2003 Emulator 转中文版
    BSTR转CString
    在pocket pc 2003上播放声音
    VC++.net 2005 SmartDevice 屏幕转向
    c#.net2005 调用evc4.0生成的dll文件
    Json
    adb 命令模拟按键事件
    bat 截取字符
  • 原文地址:https://www.cnblogs.com/hello-tomorrow/p/9313101.html
Copyright © 2020-2023  润新知