Codeforces Round #462 (Div. 2) D A Determined Cleanup

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Lfhase/article/details/79328132

题目链接:点击打开链接

题意:给定k,p,求一个各系数都为小于k的非负数的多项式f(x),使得存在一个多项式q(x),有f(x) = q(x)(x+k)+p

思路:

利用多项式余数定理,即若f(x) % (x - k) = p,则f(k) = p。

这里k用-k代替即得到所求多项式为f(-k) = p,可以看作是一个-k进制下的p的表示。先求k进制下p的表示,对于每个奇数位上的数进行检查(因为-k的奇数次幂为负数)。假设某奇数位a上k进制下p的表示大于0,即需要加上一个 该位上的数(不妨设为b)*k^a,也就是加上一个 k^(a+1) - (k-b)*k^a,这里的b显然小于k。而后对后两位数进行同样的检查即可。

AC代码如下:

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <set>
#include <vector>

using namespace std;

#define FSIO  ios::sync_with_stdio(0);cin.tie(0);
#define DEBUG(a)   cout<<"DEBUG: "<<(a)<<endl;

long long num[100];
long long k, p;
long long mark[100];

void check(int p)
{
    if(p<=90&&mark[p]>=k)
    {
        mark[p+1]+=k-mark[p]/k;
        mark[p+2]+=1;
        mark[p]%=k;
        check(p+1);
        check(p+2);
    }
    else
        return;
}

int main()
{
    FSIO;
    while(cin>>p>>k)
    {
        memset(mark,0,sizeof(mark));
        num[0]=1;
        int cur=0;
        while(num[cur]<p) cur++, num[cur]=num[cur-1]*k;
        for(int i=cur;i>=0;--i)
        {
            if(p/num[i]!=0)
            {
                mark[i] = p/num[i];
                if(i%2==1)
                {
                    mark[i] = k-mark[i];
                    mark[i+1]++;
                    check(i+1);
                }
                p%=num[i];
            }
            else
            {
                mark[i] = 0;
            }
        }
        cur = 80;
        while(mark[cur]==0) cur--;
        cout<<cur+1<<endl;
        for(int i=0;i<cur;i++)
            cout<<mark[i]<<" ";
        cout<<mark[cur]<<endl;
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Lfhase/article/details/79328132