【Codeforces Round 354 (Div 2)E】【数学 多项式除法 讨论】The Last Fight Between Human and AI 多项式除以x-k是否值整除
E. The Last Fight Between Human and AItime limit per test1 secondmemory limit per test256 megabytesinputstandard inputoutputstandard output100 years have passed
100 years have passed since the last victory of the man versus computer in Go. Technologies made a huge step forward and robots conquered the Earth! It's time for the final fight between human and robot that will decide the faith of the planet.
The following game was chosen for the fights: initially there is a polynomial
Polynomial P(x) is said to be divisible by polynomial Q(x) if there exists a representation P(x) = B(x)Q(x), where B(x) is also some polynomial.
Some moves have been made already and now you wonder, is it true that human can guarantee the victory if he plays optimally?
The first line of the input contains two integers n and k (1 ≤ n ≤ 100 000, |k| ≤ 10 000) — the size of the polynomial and the integer k.
The i-th of the following n + 1 lines contain character '?' if the coefficient near xi - 1 is yet undefined or the integer value ai, if the coefficient is already known ( - 10 000 ≤ ai ≤ 10 000). Each of integers ai (and even an) may be equal to 0.
Please note, that it's not guaranteed that you are given the position of the game where it's computer's turn to move.
Print "Yes" (without quotes) if the human has winning strategy, or "No" (without quotes) otherwise.
1 2 -1 ?
Yes
2 100 -10000 0 1
Yes
4 5 ? 1 ? 1 ?
No
In the first sample, computer set a0 to - 1 on the first move, so if human can set coefficient a1 to 0.5 and win.
In the second sample, all coefficients are already set and the resulting polynomial is divisible by x - 100, so the human has won.
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<string>
#include<ctype.h>
#include<math.h>
#include<set>
#include<map>
#include<vector>
#include<queue>
#include<bitset>
#include<algorithm>
#include<time.h>
using namespace std;
void fre() { freopen("c://test//input.in", "r", stdin); freopen("c://test//output.out", "w", stdout); }
#define MS(x,y) memset(x,y,sizeof(x))
#define MC(x,y) memcpy(x,y,sizeof(x))
#define MP(x,y) make_pair(x,y)
#define ls o<<1
#define rs o<<1|1
typedef long long LL;
typedef unsigned long long UL;
typedef unsigned int UI;
template <class T1, class T2>inline void gmax(T1 &a, T2 b) { if (b>a)a = b; }
template <class T1, class T2>inline void gmin(T1 &a, T2 b) { if (b<a)a = b; }
const int N = 1e5+10, M = 0, Z = 1e9 + 7, ms63 = 0x3f3f3f3f;
int n, k;
char s[12];
int coe[N];
bool check(int val)
{
LL tmp = 0;
int mod = abs(val - k);
for (int i = n; i >= 0; --i)
{
tmp = (tmp*val + coe[i]) % mod;
}
return tmp;
}
bool divide()
{
LL tmp = 0;
for (int i = n; i >= 0; --i)
{
tmp = k*tmp + coe[i];
if (abs(tmp) >= 1e14)return 0;
}
return tmp == 0;
}
bool solve()
{
int qmark = 0;
for (int i = 0; i <= n; ++i)
{
scanf("%s", s);
if (s[0] == '?')coe[i] = 1e9, ++qmark;
else sscanf(s, "%d", &coe[i]);
}
if (k == 0)
{
if (coe[0] == 0)return 1;
if (coe[0] != 1e9)return 0;
bool IplayFirst = (n + 1 - qmark & 1);
return IplayFirst;
}
if (qmark)
{
bool IplayLast = (n % 2 == 1);
return IplayLast;
}
else
{
return divide();
for (int tim = 1; tim <= 50; ++tim)
{
if (check(rand()%10000*rand()))return 0;
}
return 1;
}
}
int main()
{
while (~scanf("%d%d", &n, &k))
{
puts(solve() ? "Yes" : "No");
}
return 0;
}
/*
【trick&&吐槽】
样例1:
1 2
- 1 x ^ 0
0.5 x ^ 1
- 1 + 0.5x = (x - 2)(0.5)
样例2:
2 100
- 10000 x ^ 0
0 x ^ 1
1 x ^ 2
- 10000 + x ^ 2 = (x - 100)(x + 100)
【题意】
给你一个多项式,
最高项为n次,也就是说,该多项式可以写作:
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
然而系数a[]有的填了有的没填
总体上的操作顺序是先robot再human,目前谁先手不确定。
问你,是否有一个填充方案使得使得我们在把a[]填奥之后,
满足这个多项式/(x-k),得到的结果依然是一个多项式(具体参考样例)
n∈[1,1e6]
k∈[-1e4,1e4]
【类型】
多项式除法问题
随机数乱搞大法
【分析】
我们首先要学会观察。
1,数据规模要求我们只有用O(n)级别的算法才能AC
2,除以的式子是(x-k),
我们发现该多项式,除了最低项a[0]以外,其它项都至少含有一个x。
于是,
一,如果k==0,这种情况下,我们只要使得a0不为0即可。
1,a[0]已填,则填0必胜,填其它必败
2,a[0]未填,则目前我们先手则必胜,否则必败
二,如果k!=0,那么我们可以模拟一下多项式除法的过程,然后便可以发现——
如果没填完,最后一手是谁谁必胜
如果填完了,我们验证"该多项式/(x-k)"是否恒为0即可
==================
验证的方法可以是——
1,随机算法(用check())函数实现
如果"该多项式/(x-k)"恒为0,那么我们随机任何一个x,对于该多项式,最后求解都应当为0
然而,如果只是取某一个或两个模数,是可能会被hack的,所以我们要多随机!
2,除法模拟(用divide())函数实现
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)
a[n] * x^n =(x-k)* a[n]*x^(n-1) +k*a[n]*x^(n-1)
于是我们可以模拟这个过程,通过判定:(1)不溢出,(2)最后为0来验证答案的正确性
举例:
2 100
x^2-10000/(x-100)是否为0
=100x-10000是否为0
=0是否为0
=YES
【时间复杂度&&优化】
O(kn)
【数据】
hack数据:针对1e9+7 && 1e9+9
4 10000
63 0 160 0 100
63x^3 + 160x + 100
(x-10000)
*/
更多推荐
所有评论(0)