hdu4569 求解f(x)%(p*p)=0

http://acm.hdu.edu.cn/showproblem.php?pid=4569php

首先若是f(x)%(p*p)=0,則必有f(x)%p=0,所以解x必然在知足f(x)%p=0的集合中。ios

接着注意到p爲質數,f(x)爲多項式,那麼知足f(x)%p=0的集合在p的剩餘系中必然不多,而因爲f(x)爲多項式,那麼根據同餘模定理,必然有f(x+k*p*p)=f(x) (mod p*p)。所以找到知足f(x)%p=0的集合x(x在p的剩餘系中),而後枚舉k便可。ide

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<math.h>
#define REP(i,a,b) for(int i=a;i<=b;i++)
#define MS0(a) memset(a,0,sizeof(a))

using namespace std;

typedef long long ll;
const int maxn=1000100;
const int INF=1e9+10;

int n;
ll a[maxn],p;

ll qpow(ll n,ll k,ll p)
{
    ll res=1;
    while(k){
        if(k&1) res=(res*n)%p;
        n=(n*n)%p;
        k>>=1;
    }
    return res;
}

ll f(ll x,ll p)
{
    ll res=0;
    REP(i,0,n){
        res=(res+a[i]*qpow(x,i,p))%p;
    }
    return res;
}

int main()
{
    freopen("in.txt","r",stdin);
    int T;cin>>T;int casen=1;
    while(T--){
        scanf("%d",&n);
        for(int i=n;i>=0;i--) scanf("%I64d",&a[i]);
        scanf("%I64d",&p);
        REP(i,0,n){
            while(a[i]<0) a[i]+=p*p*100000;
            a[i]%=p*p;
        }
        bool flag=0;
        ll ans=-1;
        REP(x,0,p-1){
            if(f(x,p)==0){
                for(ll y=x;y<p*p;y+=p){
                    if(f(y,p*p)==0){
                        ans=y;flag=1;
                    }
                    if(flag) break;
                }
            }
            if(flag) break;
        }
        printf("Case #%d: ",casen++);
        if(flag) printf("%I64d\n",ans);
        else puts("No solution!");
    }
    return 0;
}
View Code

唉,我怎麼那麼笨,連這都沒看出來。。spa

總結,若是對於f(x)=y(mod p) ,若是f(x)爲多項式,那麼就應該善於用同餘模定理,若是找解的話,能夠考慮枚舉,但要注意枚舉的範圍,不要去枚舉那些明顯不在解集中的數。code

相關文章
相關標籤/搜索