codeforces 676E 数学多项式

外国人写的太神看不懂,网上题解随机数这种乱搞都出来了,然后无奈自己推

该方法前面证明是对的然后会超long long所以不断改变mod水过,太菜真心想不到更好的方法。
证明:
一个多项式分解成 (x-k)和另一个多项式相乘

a[n]*x^n+a[n-1]*x^(n-1)+a[n-2]*x^(n-2)+a[n-3]*x^(n-3)+…+a[0]*x^0 =
(x-k) * (b[n-1]*x^(n-1)+b[n-2]*x^(n-2)+b[n-3]*x(n-3)+…..+b[0]*x^0)

则b[n-1]*x^n+(b[n-2]-k*b[n-1])*x^(n-1)+(b[n-3]-k*b[n-2])*x^(n-2)+…..+(b[0]-k*b[1])*x-k*b0*x^0;

所以
b[n-1] = a[n];
b[n-2] = k*b[n-1] + a[n-1];
b[n-3] = k*b[n-2] + a[n-2];
……..
b[0] = k*b[1]+a[1];
-k*b[0] = a[0];

推导方法:前n个多项式就可以确定所有的解了。然后把b[0]带入最后一个方程式,如果矛盾就不行如果不矛盾就可以了。
这题就是线性代数,然而就我这线代渣渣水平推这个基本靠直觉。

然后这题的做法。如果k = 0要特殊讨论因为当k = 0时 b[0]*k必然为0;而别的b[i]无论是不是问号基本b[i] = a[i+1];所以a[0] = 0时 输出Yes不为0时输出No,a[0]为问号时看人能不能先手把它变0!

如果k!=0,就要解上面的方程了,
如果有问号的话那有用的式子小于等于n个,根据记忆中的线代定理可以确定一组可行解,但电脑后手的话可以让这个可行方程变得矛盾。。。
如果没有问号递推求方程按上面推导方法求出答案。

问题在于超long long 但只能想出这一种办法

#include
#include
#include
#include
using namespace std;
#define LL long long
#define mod 4000000017ll  //乱搞 
string a[110000];
LL n,k;
LL ans[110000];

LL transform(string a)
{
    LL l = a.size(),ans = 0,pre = 1;
    for(int i=l-1;i>=0;i--)
    {
      if(a[i]=='-')break;
      ans+=(a[i]-'0')*pre;
      pre*=10;
   }
   if(a[0]=='-')ans = -1*ans;
   return ans;
}

int main()
{
    scanf("%I64d%I64d",&n,&k);
    int sum = 0;
    for(int i=0;i<=n;i++)
    {
        cin>>a[i];
        if(a[i]=="?")sum++;
        ans[i] = transform(a[i]);
    }
    if(k==0)//k为0 
    {
        if(a[0]=="?"){
             if((n+1-sum+1)%2)printf("No\n");
             else printf("Yes\n");
        }
        else 
        {
           if(a[0]=="0")printf("Yes\n");
           else printf("No\n");
        }
    }
    else if(!sum)//无问号 
    {
       LL w = 0;
       for(int i=n;i>=1;i--)
       {
           w = k*w+ans[i];
           w%=mod;
       }
       if(-1*w%mod*k%mod==ans[0]%mod)printf("Yes\n");
       else printf("No\n");
    }
    //有问号 
    else{                          
        if((n+1)%2)printf("No\n");
        else printf("Yes\n");
    }
    return 0;
}

你可能感兴趣的:(多项式)