Codeforces 658D Bear and Polynomials【数学】

题目链接:

http://codeforces.com/contest/658/problem/D

题意:

给定合法多项式,改变一项的系数,使得P(2)=0,问有多少种方法?

分析:

暴力求和然后依次试一试肯定不行啦~
仔细想想,多项式和为0,就是说存在某个2i,使得剩下的和等于x2i,(其中x 的绝对值小于等于k)。
那我们就从最小的开始看。把系数依次向后移。
如果系数ai为偶数,那么ai2i=(ai/2)2i+1,就令bi=0,否则bi=1,最终所有系数都移到了2n上。
如果某个bi为奇数的话,就是说不能完全转化成后面的数,无法用比他大的数表示他,那么后面的系数怎么变也抵消不了。所以我们只能看他自己和他前面的元素,通过改变这些元素的系数试图抵消它。
最后倒着算一遍,算出对于每个位置,可以抵消后面的数的系数,然后。。。减一下他自己。。。就可以了。。。。
然后注意一下倒着求和过程中res的绝对值大于INF的情况,直接break。

代码:

#include <cstdio>
const int maxn = 200005, INF = 1e18;
long long t[maxn],a[maxn], b[maxn];
int main (void)
{
    int n, k;
    long long res = 0;
    scanf("%d%d",&n, &k);
    for(int i = 0; i <= n; i++){
        scanf("%I64d",&a[i]);
    }
    b[n] = a[n];
    int flag;
    for(int i = 0; i < n; i++){
       int tmp = b[i] + a[i] ;
       b[i + 1] += tmp / 2ll;
       b[i] = tmp % 2ll;
    }
    for(int i = 0; i <= n; i++){
        if(b[i]){flag = i; break;}//记录
    }
    int cnt = 0;
    for(int i = n; i >= 0; i--){
         res = res * 2ll + b[i];
        if(res > INF || res < -INF )break;
        if(i <= flag){
            int ans = a[i] - res;
            if(ans >= -k && ans <= k && (ans != 0 || i != n)){
                cnt++;
            }
        }
    }
   printf("%d\n", cnt);
}
/*
5 5
0 -4 -2 -2 0 5
*/

智商压制,想的有点久。。。不过还是涨姿势!

posted @ 2016-03-29 17:12  zhuyujiang  阅读(207)  评论(0编辑  收藏  举报