[HDU 4569] Special equations (数学+技巧+脑洞)

HDU - 4569
给你一个多项式,求使得多项式 mod (P*P)的平方为 0的解

刚开始题目扯了一堆 CRT啥啥啥的,其实是烟雾弹
注意到这题 P只有 1e4,意味着可以从 0..P-1 枚举出 x的解
因为根据 mod 的性质,以及 f(x)是多项式
如果 f(x)%P=0,那么 f(x+P)%P=0
所以只需要枚举 0..P-1就好了
但是这题求的是 mod P*P就比较麻烦,乘起来是 1e8,不可能枚举
所以意味着上面说的方法不行……

然而真的不行吗,看了下题解,正解就是这个……
实际上,如果 mod P*P为 0,那么首先 mod P要为 0
如果 f(x) mod P为 0的情况下,再去枚举 x+k*P 到 P*P
这样看起来还是会 T,但实际上解是比较稀疏的
所以 mod P的判定可以剪掉很多,而最终不会 T

艺高人胆大啊,是在下输了……
以后碰到不会的题,还是先别急着 GG
没准就是个玄学复杂度的暴力呢 orz
好像关于因子和模的题,玄学复杂度的还真不少

#include <cstdio>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <map>
#include <set>
#include <queue>
using namespace std;
typedef pair<int,int> Pii;
typedef long long LL;
typedef unsigned long long ULL;
#define MST(a,b) memset(a,b,sizeof(a))
#define CLR(a) MST(a,0)
#define Pow2(a) (a*a)

int deg;
LL a[5],P;

bool func(LL x, LL mod)
{
    LL res=0,now=1;
    for(int i=0; i<=deg; i++)
    {
        res=(res+now*a[i])%mod;
        now=(now*x)%mod;
    }
    if(res%mod) return 0;
    return 1;
}

int main()
{
    int T;
    scanf("%d", &T);
    for(int ck=1; ck<=T; ck++)
    {
        scanf("%d", &deg);
        for(int i=deg; i>=0; i--) scanf("%lld", &a[i]);
        scanf("%lld", &P);
        LL ans=-1;
        for(LL i=0; i<P; i++)
        {
            if(!func(i,P)) continue;
            for(LL j=i; j<=P*P; j+=P)
            {
                if(!func(j,P*P)) continue;
                ans=j;
                goto END;
            }
        }
        END:;
        printf("Case #%d: ", ck);
        if(~ans) printf("%lld\n", ans);
        else puts("No solution!");
    }
    return 0;
}

你可能感兴趣的:([HDU 4569] Special equations (数学+技巧+脑洞))