题解 luoguP4593 【[TJOI2018]教科书般的亵渎】

传送门

先算出所需亵渎个数 k k k,观察就可以发现 k = m + 1 k=m+1 k=m+1,有一个小细节,如果从 n n n开始有一段连续的空位,应该把它去掉,因为不会需要多余的亵渎。

我们计算每一次亵渎的贡献,第一次亵渎我们认为是在 0 0 0位置。显然第一次的贡献是 i = 1 n i k \sum\limits_{i=1}^{n}i^k i=1nik - 空位的贡献。

之后我们考虑在一个空位上使用亵渎,设空位为 p p p,那么有贡献的区间为 p + 1 n p+1 \sim n p+1n。贡献为 i = 1 n p i k \sum\limits_{i=1}^{n-p}i^k i=1npik

最后我们减去空位多算的贡献即可。

考虑计算 i = 1 n i k \sum\limits_{i=1}^{n}i^k i=1nik,可利用拉格朗日插值,参考这里

C o d e <mtext>   </mtext> B e l o w : Code\ Below: Code Below:

#include<bits/stdc++.h>
#define ts cout<<"ok"<<endl
#define int long long
#define hh puts("")
#define mo 1000000007
using namespace std;
int n,m,a[55],k,f[55],pre[55],suf[55],fac[55],ans;
map<int,int> ma;
inline int read(){
    int ret=0,ff=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-') ff=-ff;ch=getchar();}
    while(isdigit(ch)){ret=(ret<<3)+(ret<<1)+ch-'0';ch=getchar();}
    return ret*ff;
}
void write(int x){
    if(x>9) write(x/10);
    putchar(x%10+48);
}
inline int ksm(int x,int y){
    int res=1;
    while(y){
        if(y&1) res=res*x%mo;
        y>>=1;
        x=x*x%mo;
    }
    return res;
}
inline int calc(int p){
    if(p<=k+2) return f[p];
    int res=0;
    pre[0]=1;
    for(int i=1;i<=k+2;i++) pre[i]=pre[i-1]*(p-i)%mo;
    suf[k+3]=1;
    for(int i=k+2;i>=1;i--) suf[i]=suf[i+1]*(p-i)%mo;
    for(int i=1;i<=k+2;i++){
        int x=pre[i-1]*suf[i+1]%mo;
        int fu=((k+2-i)&1)?-1:1;
        int y=fac[i-1]*fac[k+2-i]*fu%mo;
        res=(res+f[i]*x%mo*ksm(y,mo-2)%mo)%mo;
    }
    return (res+mo)%mo;
}
signed main(){
    fac[0]=1;
    for(int i=1;i<=52;i++) fac[i]=fac[i-1]*i%mo;
    int T=read();
    while(T--){
        n=read(),m=read();
        k=m+1;
        ma.clear();
        for(int i=1;i<=m;i++) a[i]=read(),ma[a[i]]=1;
        sort(a+1,a+m+1);
        while(ma[n]) n--,k--,m--;
        for(int i=1;i<=k+2;i++) f[i]=(f[i-1]+ksm(i,k))%mo;
        ans=calc(n);
        for(int i=1;i<=m;i++) ans=(ans-ksm(a[i],k))%mo;
        for(int i=1;i<=m;i++) ans=(ans+calc(n-a[i]))%mo;
        for(int i=1;i<=m;i++)
            for(int j=i-1;j>=1;j--)
                ans=(ans-ksm(a[i]-a[j],k))%mo;
        write((ans+mo)%mo),hh;
    }
    return 0;
}
全部评论

相关推荐

2025-11-21 03:09
已编辑
南昌大学 golang
bg普211本,走的golang后端方向。找实习经历:最近一个月投了一些日常,面了4场,都是一面挂。简历包装成分比较多,当时这个简历准备了两个星期,问AI解决什么问题用什么技术,跟其他技术对比优缺点在哪,等等。但是面试的时候一些基础的八股都答的模模糊糊,然后项目延伸的场景题一点不会。有点害怕面试,面前焦虑…本文可能带点碎碎念…省流就是因为每周面心态不行,不知道先学什么以及三天打鱼两天晒网…现在的主要问题,一个是只能依靠即时满足无法撑过枯燥的学习,另一个是难以调整心态,面试焦虑。个人背景:主包其实本来是大一开始学后端的,但是当时不知道合适的学习方法(学习路线和借助AI),也社恐不太敢问学长,走了很多弯路,也没有花很多时间在后端上面(按兴趣学的只有大二上学期写了opencamp的rustlings和learning-cxx,还有玩steam的图灵完备,剩余时间比较摆烂)。结果就是现在这鬼样子,只会写crud,差不多就是会gin&nbsp;gorm基础,会写注册登录和简单业务接口,写过几种项目结构和设计模式。缺乏自己延展的能力。计算机基础:也相当差,之前大二学的计网全忘光了,操作系统60飘过。虽然大一的时候打算法竞赛(也没什么成绩就是,省二等奖收集者),但到现在一年半没碰了,就只有dfs,并查集啥的一些很基础的题目随便写,hot100链表因为竞赛没练过相当不熟练。大二下的时候,数据库课看八股,又困又累,什么都没看进去,后面自然又是全忘光了。现在我虽然有了个概览,知道后端除了crud有缓存、微服务、分布式、消息队列等等东西,知道后端架构设计是要做权衡,性能、一致性、容灾,需要通过实验测出具体的数据来做决策,但是具体的方案不会,看基础知识是真看不进去。现在的主要问题,一个是只能依靠即时满足无法撑过枯燥的学习,另一个是难以调整心态。我高中以前一直是优等生,能够享受大部分题目都会的快感,能明确地有信心自己能做出来,解题过程需要进行推理,并且做完立刻就能得到正确反馈,其中的失败调整过程长度也在可接受范围内。(喜欢写rustlings一类的语言lab和玩《图灵完备》大概也是因为这个吧…)而现在的情景相当于我成了高三但是基础知识基本不会的状态,比我当年(会基础知识只是差做题)差多了。在这种情况下去面试也是相当痛苦,因为面试是不知道范围的。每次准备都不知道先看什么,学也学不进去。明明知道面试只是为了了解真实会问什么,但是还是很焦虑,拧巴心态。学长说去投简历面试实践是为了了解自己在哪里,别人在哪里,市场在哪里,但是我似乎还没有找到收敛的下限,只是一直失败…但是我也不能确定不面试就能学进去啊,因为我大二暑假是真的一点代码都不想碰,相当烦躁,八股也不想看。现在甚至连稍微花点时间的算法题(不能即时反馈的)都不想写了。还在纠结要不要整块时间搓项目压测试试,感觉会非常花时间。可能我项目管理也是一坨。
圆规学java:27届不着急,边投边学,克服恐惧感,你现在不敢面试,你为什么认为你暑期就勇敢了,你现在的进度其实还很早,我当时大三下才开始实习,我也很焦虑着急。永远没有准备好的时候,当下努力就是最好的加油!
点赞 评论 收藏
分享
2025-12-26 14:44
复旦大学 Java
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务