<题目链接>

<转载于 >>>  >

题目大意:
给出一串n个数字,让你在这串数字中添加k个 ' + ' 号(添加后表达式合法),然后所有拆分所得的所有合法表达式之和。

解题分析:

首先,暴力的做法肯定是不可行的,复杂度必然爆炸。然后来考虑怎么求每个数字在最终结果里的贡献呢。我们这n个数字有n-1个空位置,来放置k个' + '号,不论哪一种放置方法,每个数字都要在这种情况里出现一次,但是出现时所充当的分位是不同的,这就是统计贡献的地方!再由于每个数字都是不同的单独的,所以单独考虑每个数字可能所成为的位数时不会出现重复。

第n位:只能充当某个数字的个位有C(n-1,k)种个位情况

第n-1位:能充当个位(加号必须放一个在它后面才它能成为个位),能充当十位(加号必须放一个在它后面的后面才能使他成为十位并且他和个位之间不能放置东西)   个位:C(n-2,k-1)    十位:C(n-2,k)

第n-2位:同理   个位:C(n-2,k-1)   十位:C(n-3,k-1)  百位:C(n-3,k)

.........

也就是说:

倒数第一位:贡献了C(n-1,k)次个位数

倒数第二位:贡献了C(n-2,k-1)次个位数,C(n-2,k)次十位数

倒数第三位:贡献了C(n-2,k-1)次个位数,C(n-3,k-1)次十位数,C(n-3,k)次百位数

倒数第四位:贡献了C(n-2,k-1)次个位数,C(n-3,k-1)次十位数,C(n-4,k-1)次百位数,C(n-4,k)次千位数

........

倒数第n位:贡献了C(n-2,k-1)次个位数,C(n-3,k-1)次十位数,C(n-4,k-1)次百位数,C(n-4,k)次千位数......C(n - n,k)次n位数

所以我们预处理一下组合数C(x,k-1)和C(x,k),类似求个前缀和就可以啦!

核心部分:

倒数第一位:C(n-1,k)*s[n]

倒数第二位:C(n-2,k-1)*s[n-1] + C(n-2,k)*10*s[n-1]

倒数第三位:(C(n-2,k-1) + C(n-3,k-1)*10)*s[n-2] + C(n-3,k)*100*s[n-2]

倒数第四位:(C(n-2,k-1) + C(n-3,k-1)*10 + C(n-4,k-1)*100)*s[n-3] + C(n-4,k)*1000*s[n-3]

...........

所以可以看出,每一位数字的前部分(红色)和是从第n位累和过来的,后部分(绿色)是单独处理的,所以我们可以从第n位,开始往前循环每一位到第一位,累前缀和求和即可。

#include <cstdio>
#include <cstring>
#include <algorithm>
const int M = 1e5+;
const int mod = 1e9+;
using namespace std;
typedef long long ll;
ll fac[M],inv[M],sum[M],a[M];
char s[M];
int n,k;
ll ans,mult;
ll mod_pow(ll x,ll n){
x%=mod;
ll res = ;
while(n>){
if(n&) res = res*x%mod;
x = x*x%mod;
n>>=;
}
return res;
}
void init(){
inv[]=;fac[]=;
for(int i=;i<=n;i++){
fac[i] = (fac[i-]*i)%mod;
inv[i] = mod_pow(fac[i],mod-)%mod; //费马小定理预处理记录 i! 的逆元
}
}
ll C(ll n,ll m){
if(n<||m<) return ;
if(m>n) return ;
return (((fac[n]*inv[m])%mod)*inv[n-m])%mod; //计算组合数C(n,m), n!*(m!的逆元)*((n-m)!的逆元)
}
int main()
{
scanf("%d%d",&n,&k);
init();
scanf("%s",s+);
for(int i=;i<=n;i++)
a[i] = s[i]-'';
mult = ;
for(int i=n-;i>=;i--){
sum[i] = (sum[i+]+mult*C(i-,k-))%mod; //计算该数位为红色部分的贡献,因为红色部分这一位与这一位+1的贡献有关,所以可以求部分前缀和,简化计算
mult = (mult*)%mod;
}
mult = ;
for(int i=n;i>=k+;i--){
sum[i] = (sum[i]+C(i-,k)*mult)%mod;//计算该位数绿色部分的贡献
mult = (mult*)%mod;
}
ans = ;
for(int i=;i<=n;i++)
ans = (ans+sum[i]*a[i])%mod; //乘上每个位数上的数
printf("%lld\n",ans);
}

2018-10-09

Codeforces 521C (经典)组合数取模【逆元】的更多相关文章

  1. HDU 5698 大组合数取模(逆元)

    瞬间移动 Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submis ...

  2. 组合数取模Lucas定理及快速幂取模

    组合数取模就是求的值,根据,和的取值范围不同,采取的方法也不一样. 下面,我们来看常见的两种取值情况(m.n在64位整数型范围内) (1)  , 此时较简单,在O(n2)可承受的情况下组合数的计算可以 ...

  3. [BZOJ 3129] [Sdoi2013] 方程 【容斥+组合数取模+中国剩余定理】

    题目链接:BZOJ - 3129 题目分析 使用隔板法的思想,如果没有任何限制条件,那么方案数就是 C(m - 1, n - 1). 如果有一个限制条件是 xi >= Ai ,那么我们就可以将 ...

  4. lucas定理解决大组合数取模

    LL MyPow(LL a, LL b) { LL ret = ; while (b) { ) ret = ret * a % MOD; a = a * a % MOD; b >>= ; ...

  5. 2015 ICL, Finals, Div. 1 Ceizenpok’s formula(组合数取模,扩展lucas定理)

    J. Ceizenpok’s formula time limit per test 2 seconds memory limit per test 256 megabytes input stand ...

  6. 组合数取模&&Lucas定理题集

    题集链接: https://cn.vjudge.net/contest/231988 解题之前请先了解组合数取模和Lucas定理 A : FZU-2020  输出组合数C(n, m) mod p (1 ...

  7. 排列组合+组合数取模 HDU 5894

    // 排列组合+组合数取模 HDU 5894 // 题意:n个座位不同,m个人去坐(人是一样的),每个人之间至少相隔k个座位问方案数 // 思路: // 定好m个人 相邻人之间k个座位 剩下就剩n-( ...

  8. hdu 3944 DP? 组合数取模(Lucas定理+预处理+帕斯卡公式优化)

    DP? Problem Description Figure 1 shows the Yang Hui Triangle. We number the row from top to bottom 0 ...

  9. BZOJ_2142_礼物_扩展lucas+组合数取模+CRT

    BZOJ_2142_礼物_扩展lucas+组合数取模 Description 一年一度的圣诞节快要来到了.每年的圣诞节小E都会收到许多礼物,当然他也会送出许多礼物.不同的人物在小E 心目中的重要性不同 ...

随机推荐

  1. mysql5.7设置简单密码报错ERROR 1819 (HY000): Your password does not satisfy the current policy requirements

    注:本文来源于<  mysql5.7设置简单密码报错ERROR 1819 (HY000): Your password does not satisfy the current policy r ...

  2. SQL Server 函数之日期格式化函数

    SQL Server 函数之日期格式化函数 高文龙关注0人评论612人阅读2017-09-23 13:47:07 SQL Server 函数之日期格式化函数 对于一些经常写SQL Server执行语句 ...

  3. Confluence 6 log4j 日志级别

    日志级别 DEBUG - 被设计为用来获得最多的信息和事件,在对应用程序进行调试的时候,这个日志级别通常能够提供最多的有效信息(查看应用程序怎么了) INFO - 有关系统正常运行-计划任务运行,服务 ...

  4. numpy:dot与multiply

    http://blog.csdn.net/iamzhangzhuping/article/details/52370241

  5. 自己没有记住的一点小知识(ORM查询相关)

    一.多对多的正反向查询 class Class(models.Model): name = models.CharField(max_length=32,verbose_name="班级名& ...

  6. Python基础之re模块(正则表达式)

    就其本质而言,正则表达式(或 RE)是一种小型的.高度专业化的编程语言,(在Python中)它内嵌在Python中, 并通过 re 模块实现.正则表达式模式被编译成一系列的字节码,然后由用 C 编写的 ...

  7. Burp Scanner Report

    1.使用application web 漏洞平台,除此之外还有一款类似的工具 叫做mulidata,其实mulidata功能更好一点. 2.配置之前的问题处理 安装之前要确认 自己之前是否安装过 Ap ...

  8. Nginx详解二:Nginx基础篇之Nginx的优点

    Nginx是一个开源且高性能.可靠的HTTP中间件.代理服务 常见的HTTP服务: HTTPD--Apache基金会 IIIS--微软 GWS--Google(不对外开放) Nginx优势: 一.IO ...

  9. JS实现继承的几种方式(转)

    转自:幻天芒的博客 前言 JS作为面向对象的弱类型语言,继承也是其非常强大的特性之一.那么如何在JS中实现继承呢?让我们拭目以待. JS继承的实现方式 既然要实现继承,那么首先我们得有一个父类,代码如 ...

  10. Jenkins删除或替换All view

    一.Jenkins删除All view “系统管理”→“系统设置”页面,更改“Default view”的下拉选项.(前提你已经新建了新的view) 二.My Views删除All view “用户” ...