题目描述:
Limak is a little polar bear. He doesn't have many toys and thus he often plays with polynomials.
He considers a polynomial valid if its degree is n and its coefficients are integers not exceeding k by the absolute value. More formally:
Let a0, a1, ..., an denote the coefficients, so . Then, a polynomial P(x) is valid if all the following conditions are satisfied:
- ai is integer for every i;
- |ai| ≤ k for every i;
- an ≠ 0.
Limak has recently got a valid polynomial P with coefficients a0, a1, a2, ..., an. He noticed that P(2) ≠ 0 and he wants to change it. He is going to change one coefficient to get a valid polynomial Q of degree n that Q(2) = 0. Count the number of ways to do so. You should count two ways as a distinct if coefficients of target polynoms differ.
Input
The first line contains two integers n and k (1 ≤ n ≤ 200 000, 1 ≤ k ≤ ) — the degree of the polynomial and the limit for absolute values of coefficients.
The second line contains n + 1 integers a0, a1, ..., an (|ai| ≤ k, an ≠ 0) — describing a valid polynomial . It's guaranteed that P(2) ≠ 0.
Output
Print the number of ways to change one coefficient to get a valid polynomial Q that Q(2) = 0.
Examples
Input
3 1000000000
10 -9 -3 5
Output
3
Input
3 12
10 -9 -3 5
Output
2
Input
2 20
14 -7 19
Output
0
题目大意:
给你一个P多项式:你可以改变多项式P中的系数(题目还有约束条件,这里只是大概题意),使得P(2) = 0。问有多少种方法?
解题报告:
1:说了很多,一堆。还是删了,我决定还是举个例子,通过做这个例子,方便自己以后温习这题。
2:就拿第二组测试样例来说:
3 12
10 -9 -3 5
不修改任何系数就是这样的多项式:。一步一步往上靠近。
得到处理后的系数:0 0 -1 1 1
下标: 1 2 3 4 5
3:稍加思考就知道,当我们改变下标4的系数时,结果都不会影响1到3的系数,此时不管改成什么都不是使结果为0。可知只能修改到第一个不为0的系数(包括这个系数)。
4:那么答案出来了吗?答案是否定的。还有个系数的绝对值不能大于k的条件。现在我们就可以一步一步解出系数。
直接解的话肯定是会爆long long。我们可以处理到第一个不为0系数的下标idx。前面都是0相乘,可以忽略。假设原来的系数在num数组中,需要修改的系数为x,处理后的系数数组为dic,可以得到:
两边相除,解出x。这不可以将操作倒着处理,就相当于两边都整除了。
5:当发现对后面的后缀处理已经大于k的两倍了,就可以跳出循环了。
6:还要注意n次项的系数不能为0。
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N = 200000+10;
const ll INF = 2e9+10;
ll dic[N], idx[N];
int main(){
ll n, k, ii;
scanf("%lld%lld", &n, &k);
for(ll i=0; i<=n; ++i)scanf("%lld", idx+i), dic[i] = idx[i];
for(ll i=1; i<=n+1; ++i)dic[i] += dic[i-1]/2, dic[i-1] %= 2;
for(ll i=0; i<=n+1; ++i){
if(dic[i]){
ii = i;
break;
}
}
ll x = 0, ans = 0;
for(ll i=n+1; i>=0; --i){
x = x*2+dic[i];
if(abs(x) > INF)break;
if(i > ii || i == n+1 || (i == n && x == idx[i]))continue;
if(abs(x - idx[i]) <= k)++ans;
}
printf("%lld\n", ans);
return 0;
}
可能题解写的有点乱,但仔细阅读还是可以懂的。
baronLJ 发布了164 篇原创文章 · 获赞 4 · 访问量 1万+ 私信 关注