D - Bear and Polynomials CodeForces - 658D
题目链接:https://codeforces.com/problemset/problem/658/D
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 ≤ 109) — 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
3 1000000000
10 -9 -3 5
3
3 12
10 -9 -3 5
2
2 20
14 -7 19
0
Note
In the first sample, we are given a polynomial P(x) = 10 - 9x - 3x2 + 5x3.
Limak can change one coefficient in three ways:
- He can set a0 = - 10. Then he would get Q(x) = - 10 - 9x - 3x2 + 5x3 and indeed Q(2) = - 10 - 18 - 12 + 40 = 0.
- Or he can set a2 = - 8. Then Q(x) = 10 - 9x - 8x2 + 5x3 and indeed Q(2) = 10 - 18 - 32 + 40 = 0.
- Or he can set a1 = - 19. Then Q(x) = 10 - 19x - 3x2 + 5x3 and indeed Q(2) = 10 - 38 - 12 + 40 = 0.
In the second sample, we are given the same polynomial. This time though, k is equal to 12 instead of 109. Two first of ways listed above are still valid but in the third way we would get |a1| > k what is not allowed. Thus, the answer is 2 this time.
题目大意:问能不能改变一个系数使Q(2)=0;
思路:很容易想到暴力,直接求个总的值,再减去每个位置上的值不就好了吗,但是看清楚数据范围,这样写稳稳的错,2^n,用大数也不行,稳稳超时
所以我们要解决的就是怎么处理这么大的数的问题。可以把每个系数看做类似在二进制下的值,先把能进位的数进位,这样到最后所有能进位的全都进到第N位了
其它位要么为0 要么为1 要么为-1 。 现在我们想想哪些位置的系数改变会得到解,我们把能进位的全部进位了,然后从0遍历到N,找到第一个不为0的位置
只有在这个位置之前的位置改变系数才有效。 为啥呢? 因为当前为不为0,只能通过前面的改变系数来抵消这一位的值,后面的都比自己大,怎么改变系数也没用吧,不可能
把这一位消掉的。 看代码:
#include<iostream> #include<cstring> #include<algorithm> #include<cstdio> #include<vector> #include<queue> #include<list> using namespace std; typedef long long LL; typedef unsigned long long ull; const int maxn=2e5+5; const int maxm=100000+10; const ull base=2333; const LL INF=1e10; LL a[maxn],b[maxn]; int main() { LL N,K,sum=0,l;scanf("%lld%lld",&N,&K); for(int i=0;i<=N;i++) { scanf("%lld",&a[i]);b[i]=a[i]; } for(int i=0;i<N;i++) { a[i+1]+=a[i]/2;a[i]%=2; } for(int i=0;i<=N;i++) { if(a[i]) { l=i;break; } //找到第一个不为0的地方 只有从0-这个地方改变值才有效 //因为只能改一个位置 如果改了后面的位置 这个位置的值就无法清空了 因为后面的都比它大啊 } LL ans=0; for(int i=N;i>=0;i--) { sum=sum*2+a[i]; if(abs(sum)>INF) break; if(i<=l)//修改的位置有效 而此时的sum也就是总的sum { LL x=abs(sum-b[i]); if(x==0&&i==N) continue;//题目中的限制条件 N为不能为0 if(x<=K) ans++; } } printf("%lld\n",ans); return 0; } /** */