VK Cup 2016 - Round 1 (Div. 2 Edition)----D Bear and Polynomials 数论+二进制,很好的题!!!

定义一个多项式= a0 x^0 +a1*x^1+a2 * x^2+a3 *x^3…………….an *x^n
x=2
先给一个多项式P
保证P(2)!=0; 现在要求你可以改变某一个(只可以改变一个)系数ai —–>bi 得到另外一个多项式Q, 并且要满足Q(2)=0;

想了很久,自己感觉是个数论题,然后感觉自己在浩淼的数论面前对力量一无所知!最后GG,之后看到一个真的巨骚的解法,也许在别人面前是很常用的方法,但是由于自己很弱,以前接触过但是从来没有用过这种方法:也就是转换成二进制方面的问题来解决。

因为x=2, 而且在二进制里面:
2=10
2^2=100
2^3=1000
2^4=10000
2^5=100000
……..
2^n=1000……(n个0)
所以对于一个多项式,我们可以对每一位ai*x^i,处理成(ai%2 +ai/2)*2^i;
比如 a2=9 即 9* 2^2=(1+4*2 )* 2^2=1 *2^2 + 4*2^3; 所以a2可以进4 给a3
依次处理直到n+1;
可以得到二进制数(前n位): 由 0、1、-1 三个数组成,n+1位的数字可能是个比较大的数(暂时先不讨论)
这样该题需要解决的问题 Q(2)=0 便可以转换为二进制中所有位的数字都=0;
那么我们讨论一个问题:
一个二进制数 an,an-1,…………ai………..a1,a0
………………………..高位……………………………………低位
如果 a1!=0,那么 我们无论怎么改变ai的值都使a1发生改变,换句话说:如果存在低位不等于0,那么我们无论怎么改变高位,都无法使整个数变为0,因为高位不能改变低位。 但是低位由于可以除2进位,所以低位是可以改变高位的(只要在k范围内)

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<stdlib.h>
#include<queue>
#include<stack>
#include<map>
#include<vector>
#define mem(a) memset(a,0,sizeof(a))
using namespace std;
const int N = 200005;
#define ll long long
int x[N],a[N];
int main(){
    int j,n,i,k,ans=0;
    cin>>n>>k;
    for(i=0;i<=n;++i){
        int num;
        scanf("%d",&num);
        x[i]+=num;
        a[i]= num;
        x[i+1]+= x[i]/2;
        x[i]%=2;
    }
    ll cur = x[n+1];
    int pos;
    for(i=0;i<=n;++i){
        pos = i;
        if(x[i]!=0)break;
    }
    for(i=n;i>=0;--i){
        cur= cur*2;
        cur += x[i];
        if(abs(cur)>k*2)break;

        if(pos<i)continue;
        if(abs(cur-a[i])<=k && ( i!=n || cur!=a[i]))
            ans++;
    }
    cout<<ans<<endl;
}

你可能感兴趣的:(VK Cup 2016 - Round 1 (Div. 2 Edition)----D Bear and Polynomials 数论+二进制,很好的题!!!)