长沙邀请赛E题解题报告

时间:2021-03-27 04:04:09

大致题意:
     给出一个f(x)=an*x^n+......+a1*x+a0,看能否找到一个x使得f(x)%(pri*pri)==0成立,其中pri为一个素数(pri<=10000);  abs(an)<=100;  当f(x)系数的个数n>=3时,abs(ai)<10000, 否则abs(ai)<=100000000 (i

输入
   第一行输入测试用例的个数,
   第二行的第一个数表示f(x)系数的个数,即为n;接着后面输入an~a0  n个整数;最后输入一个素数pri。

输出
   输出任意一个使得f(x)%(pri*pri)成立的x,否则输出"No solution!"。

 

  解题思路:

 如果存在一个x使得f(x)%(pri*pri)==0成立,那么该x一定能使f(x)%pri==0成立;因此f(x)%pri==0f(x)%(pri*pri)==0成立的必要不充分条件;

因此要找到一个使得f(x)%(pri*pri)==0成立的x,首先得找到一个使得f(x1)%pri==0成立的x1;然后再从x1~pri*pri之间开始枚举,每次加pri(每次加pri是为了使f(x)每次增加的值是pri的倍数,从而保证f(x)%pri==0能够成立),看能否找到一个x使得f(x)%pri*pri==0成立。

 

 如果在1pri*pri之间没有找到一f(x)%(pri*pri)==0成立的x,那么就不存在一个x使得f(x)%(pri*pri)==0成立。

解释

对于任意一个大于pri*pri的数n,我们都可以将其成写n=(pri*pri)*t+k的形式,其中t为整数,k<=pri*pri;那么f(pri*pri*t+k)的值就相当于在f(k)的值的基础上增加了pri*pri的倍数;

所以若f(k)%pri*pri==0不成立,则f(pri*pri*t+k)%pri*pri==也不会成立;因此若在1pri*pri之间不能找到一个x使得  f(x%pri*pri==0成立,那么就不存在一个x使得f(x%pri*pri==0成立

 

代码:

#include <stdio.h>

#include <stdlib.h>


int main()

{

    int t,n,i,j,k,x1,z;

    int a[7],flag[100005];//a数组用来保存ai,flag数组用来保存用来保存能使f(x1)%pri==0成立的x1

    int pri;

    long long sum,x;

    scanf("%d",&t);//输入测试用例的个数

    for(z=1;z<=t;z++)

    {

        k=0;

        memset(flag,-1,sizeof(flag));

        scanf("%d",&n);//输入f(x)系数的个数

        for(i=n; i>=0; i--)

            scanf("%d",&a[i]);//输入an到a0


        scanf("%d",&pri);//输入一个素数



        for(i=1; i<=pri; i++)//枚举1到pri之间的数,找出使得f(x)%prii==0成立的x1

        {

            x=i;

            sum=a[0];

            for(j=1; j<=n; j++)//对于每个数值x来计算f(x)的数值

            {

                sum+=a[j]*x;

                if(sum>=pri*pri)sum%=(pri*pri);//当sum的数值大于pri*pri时,进行取余

                x*=x;

            }


            if(sum%pri==0)flag[k++]=i;//保存每个使得f(x1)%pri==0成立的x1


            if(sum%(pri*pri)==0)//判断在1到pri之间是否找到了一个x使得f(x)%pri*pri==0成立

                break;

        }


        if(i<=pri)printf("Case #%d: %d\n",z,i);//如果找到符合条件的x则输出来



        else if(flag[0]!=-1)//当在1到pri之间没找到一个使得f(x)%pri*pri==0成立的x时

        {

            for(x1=0; x1<k; x1++)//利用上一步保存下来的x1,从x1+pri开始枚举,每次加上一个pri

                                // 枚举到pri*pri为止,看能否找到一个符合条件的x

            {

                for(i=flag[x1]+pri; i<=pri*pri; i+=pri)//对于每个x1开始进行枚举

                {

                    x=i;

                    sum=a[0];

                    for(j=1; j<=n; j++)//对于每个枚举出来的x,代入f(x)中进行运算

                    {

                        sum+=a[j]*x;

                        if(sum>=pri*pri)sum%=(pri*pri);

                        x*=x;


                    }


                    if(sum%(pri*pri)==0)//判断枚举出来的x是否符合条件

                        break;

                }


                if(sum%(pri*pri)==0)//判断枚举出来的x是否符合条件,如果符合则结束枚举

                    break;

            }


            if(i<=pri*pri)printf("Case #%d: %d\n",z,i);//如果找到符合条件的x则输出来


            else printf("Case #%d: No solution!\n",z);//否则输出No solution!

        }


        else  printf("Case #%d: No solution!\n",z);//当在1到pri之间没有找到了一个x使得f(x)%pri==0成立时


    }

    return 0;

}

http://acmicpc.info/archives/1396