北信科1011 K. paulzhou和方程 [组合数学+差分序列]【数学】

题目链接:http://acm.hdu.edu.cn/diy/contest_showproblem.php?cid=31989&pid=1011
———————————————————————————————————————————
K. paulzhou和方程

Time Limit : 3000/1000ms (Java/Other) Memory Limit : 65535/102400K (Java/Other)
Total Submission(s) : 28 Accepted Submission(s) : 7
Font: Times New Roman | Verdana | Georgia
Font Size: ← →
Problem Description
众所周知,paulzhou的数学不太好。现在他有一个问题,希望你帮他解答:
给定一元n次方程 fx=c0+c1x+c2˙x2+...+cn˙xn
定义 fi 的前k项和

ski=0k1fi

现给出n、n+1个各项的系数 ci 以及k,求 sk%10007

其中
Input
第1行输入T(1≤T≤10),代表有T组数据。
紧接着每3行分别为n,各项系数,k,输入数据均为正整数。
Output
每组测试数据输出一行,输出 fx 的前k-1项和

ski=0k1fi
并对10007取模。
Sample Input
1
4
1 -2 3 1 0
3
Sample Output
21
Author
Kirai
———————————————————————————————————————————

这题用到了差分序列 详情见《组合数学(原书第5版)》翻译版 P169

查分序列:
设有一个序列 h0,h1,h2,,,,hn
它的一阶差分序列是

hi=hi+1hi

对应二阶差分序列为
2hi=hi+1hi

由此得到差分表(看起来很难看啊 意思意思就行了)

h0    h1    h2    h3.....h0    h1    h2........

根据性质能够得到(证明看书吧..)

hx=i=0nC(x,i)ihi

i=0nj=0k1C(j,i)ih0


i=0nC(m,i)=C(n+1,m+1)


i=0nj=0k1C(j,i)ih0=i=0nC(k,i+1)ih0

注:取模的时候最好都(x%MOD+MOD)%MOD

附本题代码
———————————————————————————————————————————

#include <bits/stdc++.h>
typedef long long int LL;
using namespace std;

#define abs(x) (((x)>0)?(x):-(x))

const LL N = 1e5+10;
const LL M = 10007;

/******************************************/
LL n,a[N],h[N],b[N];
LL k;

LL fac[M],inv[M];

LL qmod(LL a,LL b){
    LL res=1;
    while(b){
        if(b&1) res=res*a%M;
        b>>=1,a=a*a%M;
    }
    return res;
}

void init(){
    fac[0]=1;
    for(LL i=1;i<M;i++) fac[i]=fac[i-1]*i%M;
    inv[M-1]=qmod(fac[M-1],M-2);
    for(LL i=M-2;i>=0;i--) inv[i]=inv[i+1]*(i+1)%M;
}

LL C(LL n,LL m){
    return fac[n]*inv[m]%M*inv[n-m]%M;
}

LL Combination(LL n, LL m){
    if(n<m) return 0;
    if(n<M&&m<M) return C(n,m);
    return Combination(n/M,m/M)*Combination(n%M,m%M)%M;
}

int main(){
    init();
    LL _;scanf("%lld",&_);
    while(_--){
        scanf("%lld",&n);
        for(LL i=0;i<=n;i++) scanf("%lld",&a[i]),a[i]=a[i]%M;
        scanf("%lld",&k);
        for(LL i=0,j,x;i<=n;i++){
            for(h[i]=j=0,x=1;j<=n;j++){
                h[i]=(h[i]+a[j]*x%M)%M;
                h[i]=(h[i]%M+M)%M;x=x*i%M;
            }
        }

        b[0]=h[0];
        for(LL i=1;i<=n;i++){
            for(LL j=0;j<=n-i;j++)
                h[j]=(h[j+1]-h[j]+M)%M;
            b[i]=h[0];
        }

        LL ans = 0;
        for(LL i=0;i<=n;i++){
            ans = ans + b[i]*Combination(k,i+1)%M;
            ans = (ans%M+M)%M;
        }
        printf("%lld\n",ans);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值