HDU 4569Special equations2012长沙邀请赛E题(数学知识)

Special equations

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 178    Accepted Submission(s): 87
Special Judge

Problem Description
Let f(x) = a nx n +...+ a 1x +a 0, in which a i (0 <= i <= n) are all known integers. We call f(x) 0 (mod m) congruence equation. If m is a composite, we can factor m into powers of primes and solve every such single equation after which we merge them using the Chinese Reminder Theorem. In this problem, you are asked to solve a much simpler version of such equations, with m to be prime's square.
 
Input
The first line is the number of equations T, T<=50.
Then comes T lines, each line starts with an integer deg (1<=deg<=4), meaning that f(x)'s degree is deg. Then follows deg integers, representing a n to a 0 (0 < abs(a n) <= 100; abs(a i) <= 10000 when deg >= 3, otherwise abs(a i) <= 100000000, i<n). The last integer is prime pri (pri<=10000). 
Remember, your task is to solve f(x) 0 (mod pri*pri)
 
Output
For each equation f(x) 0 (mod pri*pri), first output the case number, then output anyone of x if there are many x fitting the equation, else output "No solution!"
 
Sample Input
4 2 1 1 -5 7 1 5 -2995 9929 2 1 -96255532 8930 9811 4 14 5458 7754 4946 -2210 9601
 
Sample Output
Case #1: No solution! Case #2: 599 Case #3: 96255626 Case #4: No solution!
 


                     题目大意: 给你函数 f(x) = a n x n  +...+ a 1 x +a 0 最多N就4位,输入任意一个x使f(x)%(prime*prime)=0。如果找不到就输出NO solution!

       解题思路:开始看到中国剩余定理有点懵了,因为以前只是刷过中国剩余定理的一些定理,而且一般都是求很多同余方程。后来有队过了,然后就认真看了下。然后决定暴力做,看了下prime的范围1~10^4,枚举的话就是10^8但是暴力超时了,因为运行测试代码就花了几秒钟。 后来就不解开始看下大白里面讲中国剩余定理。。。再最后半小时左右突然灵光一现,觉得可以先对prime取模得0之后才能继续判断。然后就立马改代码。后来WA了,事实证明当时只是有一个变量写错了。。p+=mo直接每次加mo,怎么会写成了+t!!当时想的也不是很清楚,然后就又换成了p++肯定TLE。 下来之后认真思考了下,发现是没有漏洞的。

     思考过程:如果f(x)%(mo*mo)==0的必要条件是f(x)%(mo)==0.然后f(x+k*mo)%mo==0等价于f(x)%mo==0.可以自己拿纸上画一下。当时想的主要是后面有个常数项,然后在想需不需要把它放到右边去TAT!其实是不需要的。 然后就直接在0~mo一个区间里面先找f(x)%mo==0的,如果木有直接输出No sulotion!如果有的话,就+mo判断是否可以 %(mo*mo).....思路主要是根据题目给的说是要把合数分解成几个素数相乘得来的,主要是被中国剩余定理吓到了,需要掌握的知识不能只是了解。加油! 

     题目地址:Special equations

AC代码:    
#include<iostream>
#include<cmath>
#include<cstring>
#include<string>
#include<cstdio>
using namespace std;

int a[5],n,mo,Mo;

__int64 cal1(int t) //模上mo
{
    int i,j;
    __int64 res=a[0];
    for(i=1;i<=n;i++)
    {
        __int64 tmp=a[i];
        for(j=1;j<=i;j++)
        {
            tmp=tmp*t;
            tmp=tmp%mo;
        }
        res=(res+tmp)%mo;
    }
    return res;
}

__int64 cal2(int t) //模上mo*mo
{
    int i,j;
    __int64 res=a[0];
    for(i=1;i<=n;i++)
    {
        __int64 tmp=a[i];
        for(j=1;j<=i;j++)
        {
            tmp=tmp*t;
            tmp=tmp%Mo;
        }
        res=(res+tmp)%Mo;
    }
    return res;
}

int main()
{
    int tes,cas,t,i,p;
    scanf("%d",&tes);
    for(cas=1;cas<=tes;cas++)
    {
         scanf("%d",&n);
         int flag=0;
         for(i=n;i>=0;i--)
             scanf("%d",&a[i]);
         scanf("%d",&mo);
         Mo=mo*mo;

         /*for(i=n;i>=0;i--)
            cout<<a[i]<<" ";
         cout<<mo<<endl;*/
         for(t=0;t<=mo;t++)
         {
             if(cal1(t)==0)  //筛选能模上mo的
             {
                for(p=t;p<=Mo;p+=mo)  //就是这里啊  TAT
                {
                    if(cal2(p)==0)
                    {
                        flag=1;
                        break;
                    }
                }
             }
             if(flag==1)
               break;
         }
         if(flag==1)
            printf("Case #%d: %d
",cas,p);
            else
                printf("Case #%d: No solution!
",cas);
    }
    return 0;
}


原文地址:https://www.cnblogs.com/riskyer/p/3258335.html