Codeforces Round #295 (Div. 1) C. Pluses everywhere (组合数学+乘法逆元)

2024-08-24 21:18

本文主要是介绍Codeforces Round #295 (Div. 1) C. Pluses everywhere (组合数学+乘法逆元),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

这题可以这样想:

      对于当前第i位来说,该位若在个位上出现,那么第i位和第i+1位中间肯定有一个“+”,剩下的k-1个“+”分布在剩下的n-2个空隙中,所以出现的总次数是C(n-2,k)。同理,在十位上出现的总次数是C(n-3,k)。于是每个数字的贡献值就可以求出来了,累加即可。

      所以大体思路是遍历所有可能出现的位数,从个位开始,分成两部分计算,一部分用前缀和计算出前面所有的在该位上的贡献和,另一部分算出当前位置在该位上的贡献值。

     然后对于求组合数,可以先将阶乘预处理出来,然后用乘法逆元求出组合数的值。

代码如下:

#include <iostream>
#include <string.h>
#include <math.h>
#include <queue>
#include <algorithm>
#include <stdlib.h>
#include <map>
#include <set>
#include <stdio.h>
using namespace std;
#define LL long long
#define pi acos(-1.0)
const int mod=1e9+7;
const int INF=0x3f3f3f3f;
const double eqs=1e-9;
char st[110000];
int n, k, a[110000], sum[110000];
LL fac[110000], inv_fac[110000];
LL qsm(LL n, LL k)
{LL ans=1;while(k>0){if(k&1)ans=ans*n%mod;k>>=1;n=n*n%mod;}return ans;
}
void init()
{int i;fac[0]=1;for(i=1;i<=n;i++){fac[i]=fac[i-1]*i;if(fac[i]>=mod) fac[i]%=mod;}inv_fac[n]=qsm(fac[n],mod-2);for(i=n-1;i>=0;i--){inv_fac[i]=inv_fac[i+1]*(i+1);if(inv_fac[i]>=mod) inv_fac[i]%=mod;}
}
LL comb(LL n, LL k)
{return fac[n]*inv_fac[k]%mod*inv_fac[n-k]%mod;
}
int main()
{int i;LL ans=0, base=1, s;scanf("%d%d",&n,&k);scanf("%s",st+1);init();sum[0]=0;for(i=1;i<=n;i++){a[i]=st[i]-'0';sum[i]=a[i]+sum[i-1];}for(i=1;i<=n-k;i++){s=(LL)sum[n-i]*base%mod;ans+=s*comb(n-i-1,k-1)%mod;s=(LL)a[n-i+1]*base%mod;ans+=s*comb(n-i,k)%mod;base=base*10;if(ans>=mod) ans%=mod;if(base>=mod) base%=mod;}printf("%I64d\n",ans);return 0;
}


这篇关于Codeforces Round #295 (Div. 1) C. Pluses everywhere (组合数学+乘法逆元)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1103622

相关文章

hdu4828(卡特兰数+逆元)

这题的前几个数据分别为1,2,5,14,32......................然后确定这是个卡特兰数列 下面来介绍下卡特兰数,它的递推式为f[i+1] = f[i]*(4*n - 6)/n,其中f[2] = f[3] =1;f[4] = 2;f[5] = 14;f[6] = 32.................................. 但是这题的n太大了,所以要用到逆元,

hdu4869(逆元+求组合数)

//输入n,m,n表示翻牌的次数,m表示牌的数目,求经过n次操作后共有几种状态#include<iostream>#include<algorithm>#include<cstring>#include<stack>#include<queue>#include<set>#include<map>#include<stdio.h>#include<stdlib.h>#includ

uva 10014 Simple calculations(数学推导)

直接按照题意来推导最后的结果就行了。 开始的时候只做到了第一个推导,第二次没有继续下去。 代码: #include<stdio.h>int main(){int T, n, i;double a, aa, sum, temp, ans;scanf("%d", &T);while(T--){scanf("%d", &n);scanf("%lf", &first);scanf

uva 10025 The ? 1 ? 2 ? ... ? n = k problem(数学)

题意是    ?  1  ?  2  ?  ...  ?  n = k 式子中给k,? 处可以填 + 也可以填 - ,问最小满足条件的n。 e.g k = 12  - 1 + 2 + 3 + 4 + 5 + 6 - 7 = 12 with n = 7。 先给证明,令 S(n) = 1 + 2 + 3 + 4 + 5 + .... + n 暴搜n,搜出当 S(n) >=

uva 11044 Searching for Nessy(小学数学)

题意是给出一个n*m的格子,求出里面有多少个不重合的九宫格。 (rows / 3) * (columns / 3) K.o 代码: #include <stdio.h>int main(){int ncase;scanf("%d", &ncase);while (ncase--){int rows, columns;scanf("%d%d", &rows, &col

【生成模型系列(初级)】嵌入(Embedding)方程——自然语言处理的数学灵魂【通俗理解】

【通俗理解】嵌入(Embedding)方程——自然语言处理的数学灵魂 关键词提炼 #嵌入方程 #自然语言处理 #词向量 #机器学习 #神经网络 #向量空间模型 #Siri #Google翻译 #AlexNet 第一节:嵌入方程的类比与核心概念【尽可能通俗】 嵌入方程可以被看作是自然语言处理中的“翻译机”,它将文本中的单词或短语转换成计算机能够理解的数学形式,即向量。 正如翻译机将一种语言

Codeforces Round #240 (Div. 2) E分治算法探究1

Codeforces Round #240 (Div. 2) E  http://codeforces.com/contest/415/problem/E 2^n个数,每次操作将其分成2^q份,对于每一份内部的数进行翻转(逆序),每次操作完后输出操作后新序列的逆序对数。 图一:  划分子问题。 图二: 分而治之,=>  合并 。 图三: 回溯:

Codeforces Round #261 (Div. 2)小记

A  XX注意最后输出满足条件,我也不知道为什么写的这么长。 #define X first#define Y secondvector<pair<int , int> > a ;int can(pair<int , int> c){return -1000 <= c.X && c.X <= 1000&& -1000 <= c.Y && c.Y <= 1000 ;}int m

Codeforces Beta Round #47 C凸包 (最终写法)

题意慢慢看。 typedef long long LL ;int cmp(double x){if(fabs(x) < 1e-8) return 0 ;return x > 0 ? 1 : -1 ;}struct point{double x , y ;point(){}point(double _x , double _y):x(_x) , y(_y){}point op

Codeforces Round #113 (Div. 2) B 判断多边形是否在凸包内

题目点击打开链接 凸多边形A, 多边形B, 判断B是否严格在A内。  注意AB有重点 。  将A,B上的点合在一起求凸包,如果凸包上的点是B的某个点,则B肯定不在A内。 或者说B上的某点在凸包的边上则也说明B不严格在A里面。 这个处理有个巧妙的方法,只需在求凸包的时候, <=  改成< 也就是说凸包一条边上的所有点都重复点都记录在凸包里面了。 另外不能去重点。 int