TA

A Lannister always pays his debts

躧搿螞 解题报告

给定k,a,n,d
定义

f(n)=i=1nik,g(n)=i=1nf(i)

i=0ng(a+id) mod 1234567891

多组数据。
T3
1k123;0a,n,d123456789
时限:5s,空间限制:256MB

这个题当时考试的时候没时间做了,其实还是比较可做的。
看到这么一坨吃屎的式子,首先我们可以先试着求一求g(n)。

g(n)=i=1n(ni+1)ik=(n+1)i=1niki=1nik+1

考虑xi=1ik这玩意儿显然可以用累加法递推求出来。
xk+1(x1)k+1=j=1k+1(1)jxk+1j

(x1)k+1(x2)k+1=j=1k+1(1)jxk+1j


1k+10k+1=j=1k+1(1)j

将x个方程的左右两边相加,即可得到:
xk+1=j=1k+1(1)ji=1xik+1j
,移项:
i=1xik=(k+1)1(xk+1+j=2k+1(1)ji=1xik+1j)

这样的话,我们就可以递推出xi=1ik,注意到还需要用到逆元,所以求一个g的时间复杂度边是O(k2+klog2k),当然这并没有什么卵用(其实这是60分),然后我们继续化式子。
ans=j=0n((a+jd+1)i=1a+jdiki=1a+jdik+1)

注意到对于同一个形如xi=1ik的家伙,它其实等价于一个x的k+1次多项式,我们可以在O(k3+klog2k)的时间复杂度内搞出它的各项系数,所以我们不妨设其各项系数为{ak,k+1},便可将上式化简为
ans=i=1k+1ak,ij=0n((a+jd+1)(a+jd)i)i=1k+2ak+1,ij=0n(a+jd)i
=i=1k+1ai(j=0n(a+jd)i+1+j=0n(a+jd)i)i=1k+2ak+1,ij=0n(a+jd)i

系数我们已经可以求出来了,注意里面的式子,会发现它又是我们熟悉的形如(只是形如)xi=1ik的家伙,所以我们大可用同样的方法递推它,只是递推式变成了
i=0n(a+jd)k=((k+1)d)1((a+nd)k(ad)k+j=2k+1(d)ji=0n(a+id)k+1j)

但是,真正需要注意的地方是d=0的时候!这个式子是没有意义的,也就是说d=0时不能用这个式子来求,应该单独讨论这种蛋疼的情况。
这样的话,我们就可以在O(k2+klog2P)的时间复杂度内求出这货了,然后回带回去即可,不过我们注意到k的范围比较小,所以我们可以预处理1~k的逆元,这样理论时间复杂度就降到了O(k3+log2k+Tk2+Tlog2d)106,哪怕k开到300都可以在1s以内快速出解,不知道为什么出题人把时限开到了5s。
代码:

#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
using namespace std;
#include<algorithm>
#define Mod 1234567891
typedef long long LL;
LL pow(int a,int b){
    LL ans=1,t=a;
    for(;b;b>>=1,t=t*t%Mod)
        if(b&1)
            ans=ans*t%Mod;
    return ans;
}
LL ni(int a){
    return pow(a,Mod-2);
}
LL C[130][130];
LL xishu[130][130];
LL said[135];
int main(){
    freopen("sum.in","r",stdin);
    freopen("sum.out","w",stdout);
    int k,i,j,T;
    for(i=0;i<130;++i)C[i][0]=1;
    for(i=1;i<130;++i)
        for(j=i;j;--j)
            C[i][j]=(C[i-1][j-1]+C[i-1][j])%Mod;
    xishu[0][1]=1;
    LL niyuan;
    int fu;
    for(k=1;k<130;++k){
        fu=1;
        for(j=2;j<=k+1;++j,fu=-fu)
            for(i=k+1-j+1;i;--i)
                xishu[k][i]=(xishu[k][i]+fu*xishu[k-j+1][i]*C[k+1][j])%Mod;
        niyuan=ni(k+1);
        xishu[k][k+1]=1;
        for(j=k+1;j;--j)xishu[k][j]=(xishu[k][j]*niyuan%Mod+Mod)%Mod;
    }

    scanf("%d",&T);
    LL a,n,d,start,end,fac;
    LL ans;
    int K;
    while(T--){
        scanf("%d%I64d%I64d%I64d",&K,&a,&n,&d);
        //said
        start=a,end=(a+n*d)%Mod;
        said[0]=n;
        for(k=1;k<=K+2;++k){
            start=start*a%Mod,end=end*(a+n*d%Mod)%Mod;
            fu=1;
            said[k]=(end-start)%Mod;
            fac=d*d%Mod;
            for(j=2;j<=k+1;++j,fu=-fu,fac=fac*d%Mod)said[k]=(said[k]+fu*fac*C[k+1][j]%Mod*said[k+1-j])%Mod;
            said[k]=said[k]*ni((k+1)*d%Mod)%Mod;
        }
        if(d){
            start=a;
            ++said[0];
            for(k=1;k<=K+2;++k,start=start*a%Mod)said[k]=((said[k]+start)%Mod+Mod)%Mod;
        }
        else{
            start=1;
            for(k=0;k<=K+2;++k,start=start*a%Mod)said[k]=(n+1)*start%Mod;
        }
        //cal first
        ans=0;
        for(i=1;i<=K+2;++i)ans=(ans+xishu[K+1][i]*said[i])%Mod;
        ans=Mod-ans;
        //cal second
        for(i=1;i<=K+1;++i)ans=(ans+xishu[K][i]*((said[i]+said[i+1])%Mod))%Mod;
        printf("%I64d\n",ans);
    }
}

总结:
①考试时不要思考一道题超过半小时!
②做模的时候一定要仔细想加减乘除是否会爆,每一步都可能跪!
③一定要给自己出卡范围、卡上下界的特殊数据!

阅读更多
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/TA201314/article/details/46794851
文章标签: 数论
个人分类: 数论 特殊数据
上一篇时间之主 解题报告
下一篇匹配 解题报告
想对作者说点什么? 我来说一句

ZOJ解题报告ZOJ解题报告

2010年08月02日 282KB 下载

acm解题报告.rar

2009年03月18日 10MB 下载

poj 3414解题报告

2010年04月02日 8KB 下载

poj 2329解题报告

2010年04月02日 5KB 下载

poj 3083解题报告

2010年04月02日 8KB 下载

没有更多推荐了,返回首页

关闭
关闭