您的位置:首页 > 其它

codeforces 676E 数学多项式

2016-05-26 21:22 344 查看
外国人写的太神看不懂,网上题解随机数这种乱搞都出来了,然后无奈自己推

该方法前面证明是对的然后会超long long所以不断改变mod水过,太菜真心想不到更好的方法。

证明:

一个多项式分解成 (x-k)和另一个多项式相乘



a
*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
;

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<cstdio>
#include<algorithm>
#include<string>
#include<iostream>
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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: