洛谷P1771 方程的解_NOI导刊2010提高(01)

题目描述

佳佳碰到了一个难题,请你来帮忙解决。

对于不定方程a1+a2+…+ak-1+ak=g(x),其中k≥2且k∈N,x是正整数,g(x)=x^x mod 1000(即x^x除以1000的余数),x,k是给定的数。我们要求的是这个不定方程的正整数解组数。

举例来说,当k=3,x=2时,分别为(a1,a2,a3)=(2,1,1)'(1,2,1),(1,1,2)。

输入输出格式

输入格式:

 

输入文件equation.in有且只有一行,为用空格隔开的两个正整数,依次为k,x。

 

输出格式:

 

输出文件equation.out有且只有一行,为方程的正整数解组数。

 

输入输出样例

输入样例#1:
3 2
输出样例#1:
3

说明

对于40%的数据,ans≤10^16;对于100%的数据,k≤100,x≤2^31-1,k≤g(x)。

_NOI导刊2010提高(01)

分析:考虑dp,设f[i][j]表示选了i个数,和为j的正整数解组数.很显然f[i][j]=∑f[i-1][j-kk],kk是i能够取到的数,答案是f[x^x % 1000][k].复杂度是三次方级别的,看有没有方方法来优化一下.单纯从dp上来看似乎是只能优化空间了,如果有公式就好了,类似青蛙过河一样。

      其实问题可以变成我们要走k步,每一步走的距离任意,走的总距离要为x,求方案数,因为每一步走的距离任意,实际上我们只要把这k步分配到x中就好了.把x抽象成x个点,画在图上,就能发现走k步实际上是在x-1个间隔中找k-1个间隔,那么答案就是C(x-1,k-1).

因为k,x很大,所以要用到高精度,我用结构体写高精度总是出现奇怪的错误,以后还是用数组了.

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

long long k,x;
int f[1000][110][220];

long long qpow(long long a,long long b,int mod)
{
    long long ans = 1;
    while (b)
    {
        if (b & 1)
        ans = (ans * a) % mod;
        a = (a * a) % mod;
        b >>= 1;
    }
    return ans;
}

void add(int x,int y,int x1,int y1,int x2,int y2)
{
    for (int i = 1; i <= max(f[x1][y1][0],f[x2][y2][0]); i++)
    {
        f[x][y][i] += f[x1][y1][i] + f[x2][y2][i];
        f[x][y][i + 1] = f[x][y][i] / 10;
        f[x][y][i] %= 10;
    }
    f[x][y][0] = max(f[x1][y1][0],f[x2][y2][0]);
    if (f[x][y][f[x][y][0] + 1])
    f[x][y][0]++;
}

int main()
{
    scanf("%lld%lld",&k,&x);
    x = qpow(x,x,1000);
    
    for (int i = 0; i < x; i++)
    f[i][0][0] = f[i][0][1] = 1;
    
    for (int i = 1; i < x; i++)
    for (int j = 1; j < k; j++)
    add(i,j,i-1,j,i-1,j-1);
    
    for (int i = f[x-1][k-1][0]; i >= 1; i--)
    printf("%d",f[x-1][k-1][i]);
    printf("\n");
    
    return 0;
}

 

posted @ 2017-09-08 15:26  zbtrs  阅读(403)  评论(0编辑  收藏  举报