Codeforces 995F Cowmpany Cowmpensation

题解:一般对于多种颜色染色(染色数很大>=1e8),并且染色的点很少的时候(点数<=3000)。设点数为1.可以先求出染色数(1~n+1)时所有的函数值,这样不管是对f()函数求和,还是非求和都能适用。然后套用拉格朗日差值的公式即可。f函数用dp预处理即可。

拉格朗日公式

#include"bits/stdc++.h"
using namespace std;
typedef long long ll;
const int MX = 3006;
const int mod = 1e9+7;
int fa[MX];
ll dp[MX][MX],pre[MX],suf[MX];
ll fac[MX],inv[MX];
int n,D;
int sig(int x)
{
    if(x&1) return mod-1;
    return 1;
}
void prepare()
{
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= n; j++)
            dp[i][j] = 1;
    }
    for(int i = n; i >= 1; i--){
        for(int j = 1; j <= n; j++)
            dp[i][j] = (dp[i][j]+dp[i][j-1])%mod;
        for(int j = 1; j <= n; j++)
            dp[fa[i]][j] = dp[fa[i]][j]*dp[i][j]%mod;
    }
}
void init()
{
    int n = 3003;
    fac[0] = fac[1] = inv[0] = inv[1] = 1;
    for(int i = 2; i <= n; i++){
        fac[i] = fac[i-1]*i%mod;
        inv[i] = (mod-mod/i)*inv[mod%i]%mod;
    }
    for(int i = 2; i <= n; i++)
        inv[i] = inv[i-1]*inv[i]%mod;
}

void work(ll *d, int x)
{
    pre[0] = suf[n+1] = 1;
    for(int i = 1; i <= n; i++)
        pre[i] = pre[i-1]*(x-i+mod)%mod;
    for(int i = n; i >= 1; i--)
        suf[i] = suf[i+1]*(x-i+mod)%mod;
    ll ans = 0;

    for(int i = 1; i <= n ; i++) {
        ans += pre[i-1]*suf[i+1]%mod*d[i]%mod*inv[i-1]%mod*inv[n-i]%mod*sig(n-i)%mod;
        ans = (ans%mod+mod)%mod;
    }
    printf("%lld\n",ans);
}

int main()
{
#ifdef LOCAL
    freopen("input.txt","r",stdin);
#endif // LOCAL
    init();
    scanf("%d%d",&n,&D);
    for(int i = 2; i <= n; i++){
        scanf("%d",&fa[i]);
    }
    n += 2;
    prepare();
    work(dp[1],D);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_18869763/article/details/82778550
今日推荐