• 【NOIP2014提高组】解方程


    https://www.luogu.org/problem/show?pid=2312

    对于30%的数据,n<=2,暴力带入试解。
    对于50%的数据,ai很大,结合高精乘法和霍纳算法暴力代入试解。
    高精乘法,时间复杂度是很恐怖的而且我不懂写
    注意到虽然ai很大,但是m还是在int范围内的。

    继续考虑暴力试解。
    考虑到0 mod k=0 (k∈N*),那么当f(x)=0时,f(x) mod k=0。
    但是反过来f(x) mod k=0不一定使f(x)=0成立。当k|f(x)时,f(x) mod k=0也能成立。
    为了尽可能避免这种情况,和hash一样,k取几个素数,只有膜这几个素数的时候f(x) mod k=0均成立,才判断f(x)=0成立。

    在本题中,故

    发现ai可以被膜掉,成功回避高精运算。
    实际实现的时候可以写一个和快速读入一样的东西,一边读一边膜。也可以先以字符串的形式读进来,再计算成膜k的值。

    然后发现xi也被膜掉,也就是说f(x) mod k=f(x+k) mod k。因此试解的时候只需要试[1,k)范围内的解。当然,k要取远比m小的数,这个优化才有意义。

    模几个素数呢?模多大的素数呢?这是个非常看脸的问题。少了会WA,多了会TLE。
    经过多次测试,模5个10000左右的素数是坠吼的。可是NOIP哪有机会多次测试

    #include <algorithm>
    #include <iostream>
    #include <vector>
    #include <cctype>
    #include <cstring>
    #define maxn 105
    #define maxm 1000005
    #define NUM_OF_PRIME 5
    typedef long long llint;
    using namespace std;
    const llint prime[NUM_OF_PRIME] = {9859ll, 9631ll, 9059ll, 8783ll, 8291ll};
    llint a[maxn][NUM_OF_PRIME]; //a[i][j] => i次项系数 % prime[j]
    int n, m;
    void geta(int i)
    {
        char c;
        bool flag = false;
        while (!isdigit(c = getchar()))
        {
            if (c == '-')
                flag = true;
        }
        do
        {
            for (int k = 0; k < NUM_OF_PRIME; k++)
                a[i][k] = (a[i][k] * 10 % prime[k] + c - '0') % prime[k];
        } while (isdigit(c = getchar()));
        if (flag)
        {
            for (int k = 0; k < NUM_OF_PRIME; k++)
                a[i][k] = -a[i][k];
        }
    }
    llint get_val(llint x, int k) // return f(x) mod k
    {
        llint val = 0;
        for (int i = n; i >= 0; i--)
            val = (val * x % prime[k] + a[i][k]) % prime[k];
        return val;
    }
    bool isroot[maxm];
    int main()
    {
        cin >> n >> m;
        for (int i = 0; i <= n; i++)
            geta(i);
        memset(isroot, true, m + 5);
        for (int k = 0; k < NUM_OF_PRIME; k++)
        {
            for (int i = 1; i < min(prime[k], (llint)m + 1); i++)
            {
                bool equalzero = get_val(i, k) == 0;
                for (int j = i; j <= m; j += prime[k])
                    isroot[j] &= equalzero;
            }
        }
        vector<int> ans;
        for (int i = 1; i <= m; i++)
            if (isroot[i])
                ans.push_back(i);
        cout << ans.size() << endl;
        for (int i = 0; i < ans.size(); i++)
            cout << ans[i] << endl;
        return 0;
    }
  • 相关阅读:
    ibatisnet系列
    jQuery弹出层演示
    winform中datagridview的用法
    ASP.net:截取固定长度字符串显示在页面,多余部分显示为省略号
    hdu 4507 恨7不成妻(求l,r中与7不相关数字的平方和)
    hdu 2089 数位dp
    uestc 1307 统计数位之间相差不小于2的数的个数
    Spoj 2319 数位统计(0,1, 2^k1 这些数分成M份)
    zoj 3416 统计平衡数个数
    数位统计 sgu 390 <浅谈数位类问题>
  • 原文地址:https://www.cnblogs.com/ssttkkl/p/7528902.html
Copyright © 2020-2023  润新知