51 nod 加号分配 组合数学(逆元,快速幂)

1528 加号分配
题目来源: CodeForces

基准时间限制:1 秒 空间限制:131072 KB 分值: 160 难度:6级算法题 

题目描述:

现在要给一个长度为n数字串上面加上恰好k个加号,把所有可能的算术结果相加起来。

加号加到数字串中间之后要形成正确的算术表达式。规则是:没有两个加号连在一起,两个加号之间至少要有一位数字,加号不能加在开头,也不能加在结尾。比如数字串是10500,那么100500(加0个加号),1+00+500 或者 10050+0 这些放置的加号都是合法的,而100++500, +1+0+0+5+0+0 和100500+都是非法的。
结果比较大,对 109+7 取余输出即可。
样例解释:
在第一个例子中 (1+08)+(10+8)=27。
在第二个例子中 1+0+8=9。
Input
单组测试数据。
第一行有两个整数n 和k (0≤k<n≤10^5)。
第二行包含n位数字。
Output
输出结果占一行。
Input示例
样例输入1
3 1
108
样例输入2
3 2
108
Output示例
样例输出1
27
样例输出1

9

题解:对于此类问题通常是讲n个数一位一位来看的每一个数可以作为各位数,前n-1个数可以作为十位数,前n-2位数可以作为百位数……末尾到首开始看每一位对总和的贡献=
倒数第一位:贡献了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)次千位数

1.求答案,考虑每个数作为i位数(可为答案贡献10的i-1次方,个位i=1,十位i=2,...,最多n-k位):
那么它及后面 共i个数 之间不能有加号。
且只有前n-i+1个数可以作为i位,如果是an-i+1作为i位,那么后面都不能有加号,k个加号在a1到an-i+1之间,所以有C(n-i,k)次贡献(这么说怪怪的→_←),就是几种情况。
a1 a2 a3 ... an-i+1 ... an
如果是a1、a2、...an-i作为i位,比如a1,那就是ai和ai+1之间用掉一个加号,其它加号ai+1的后面n-1-i个间隔里。
a1 a2 a3 ... ai + ai+1 ...  an
再比如a2,剩下k-1个加号在ai+2的后面及a1和a2之间 n-1-i个间隔里。
a1 a2 a3 ... ai+1 + ai+2 ...  an
所以他们都做了C(n-i-1,k-1)次贡献。
于是就有ans=∑(i=1到n-k)[(a1+a2+...an-i)*C(n-i-1,k-1)+an-i+1*C(n-i,k)]%M。
s[i]为前缀和,ans=∑(i=1到n-k)[s[n-i]*C(n-i-1,k-1)+an-i+1*C(n-i,k)]%M。
2.组合数取模
由费马小定理,当a和p互质时:ap-1≡1 mod p 可得 a*ap-2≡1 mod p,ap-2和a互为逆元。
a/b mod p=a*b-1 mod p 也就是求除数的逆元。
C(a,b)=a!/[b!*(a-b)!]
所以先求出所有1到n的阶乘,和它的逆。

计算出了n!的逆元之后,再根据n!=n*(n-1)!,两边同时乘以INV(n),INV(n-1),化简得:INV(n-1)=n*INV(n),因此可以利用该公式递推求出其他的逆元

说了这么多,就一句话:对于每一位分析它作为第i位对答案的贡献值。

总结:做题中一定要有拆的思想,因为涉及到方案数,所以很有可能和组合数学有关,而且在不同的情况下每一位的状态是不同的,所以应该把状态分开来看。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#define mod 1000000007
#define N 100005
using namespace std;
int n,k;
long long date[N],s[N];
char str[N];
long long re[N],inv[N];
long long pow(long long x)//快速幂 
{
	long long y=mod-2,ans=1;
	while(y)
	{
		if(y&1) ans=ans*x%mod;
		y>>=1;
		x=x*x%mod;
	}
	return ans;
}
void init()//求阶乘+逆元 
{
	re[0]=1;
	for(int i=1;i<=n;i++)
	    re[i]=re[i-1]*i%mod;
	inv[n]=pow(re[n]);
	for(int i=n-1;i>=0;i--)
	    inv[i]=inv[i+1]*(i+1)%mod;//o(n)求逆元 
}
long long C(long long a,long b)
{
	return re[a]*inv[b]%mod*inv[a-b]%mod; 
}
int main()
{
//	freopen("in.in","r",stdin);
//	freopen("my.out","w",stdout);
	long long ans=0,dase=1,print=0;s[0]=0;
	scanf("%d%d",&n,&k);
	scanf("%s",str+1);
	for(int i=1;i<=n;i++) date[i]=str[i]-'0',s[i]=s[i-1]+date[i];
	init();
	for(int i=1;i<=n-k;i++)
	{
		ans=(ans+s[n-i]%mod*dase%mod*C(n-i-1,k-1)%mod)%mod;
		ans=(ans+date[n-i+1]%mod*dase%mod*C(n-i,k)%mod)%mod;
		dase=dase*10%mod;
	}
	printf("%lld\n",ans);
	return 0;
}

内容概要:本研究聚焦于绿电直连型电氢氨园区的优化运行,提出一种集成绿色电力直接供给、电解水制氢及氢气合成氨工艺的综合能源系统架构。通过建立包含风光发电、电解槽、氨合成反应器、储氢罐、电网交互及多类型负荷在内的系统模型,综合考虑绿电直供优先、能量梯级利用与多能互补原则,构建以系统综合运行成本最小化为目标的优化调度模型。研究采用Matlab与Python工具进行算法求解和仿真分析,利用实际气象与负荷数据完成案例验证,评估了不同运行策略下系统的经济性、可再生能源消纳能力与碳减排效益,为新型电氢氨一体化园区的规划与运行提供了理论依据和技术支撑。; 适合人群:具备一定电力系统、新能源或化工背景的研究生、科研人员及从事综合能源系统规划与优化工作的工程技术人员。; 使用场景及目标:①用于科研学习,理解电-氢-氨多能转换系统的建模与优化方法;②为工业园区的低碳化、智能化改造提供技术参考与决策支持;③作为开发类似综合能源管理系统的理论基础。; 阅读建议:此资源包含完整的模型代码、数据与论文,使用者应结合代码仔细研读论文中的模型构建部分,重点关注目标函数与约束条件的设计逻辑,并尝试修改参数进行仿真,以深入掌握优化算法在实际系统中的应用。
内容概要:本文深入探讨了RS485通信协议在芯片行业自动化测试系统中的实际开发与应用,涵盖其关键概念、电气特性、通信机制及与Modbus RTU协议的结合使用。文章重点介绍了差分信号完整性设计、主从时序控制、CRC校验与重传机制等核心技术要点,并通过一个基于Python的完整代码实例,展示了如何实现RS485主站对探针台、自动分选机等芯片测试设备的控制与数据采集。此外,还分析了RS485在晶圆探针台、ATE设备集群和环境监控等典型场景的应用,并展望了其与工业以太网融合、智能化诊断、高速化及AI集成的发展趋势。; 适合人群:具备一定嵌入式系统或工业通信基础,从事芯片测试、自动化设备开发及相关领域的研发人员,尤其是工作1-3年希望提升现场总线应用能力的工程师。; 使用场景及目标:①理解RS485在高干扰芯片测试环境中稳定通信的设计原理;②掌握Modbus RTU协议在Python下的实现方法,用于实际控制探针台、Handler等设备;③构建可靠的数据采集与设备控制系统,支持CRC校验、异常处理和日志追踪;④为后续向高速通信和智能诊断系统升级提供技术储备。; 阅读建议:此资源强调实战开发,建议结合硬件环境动手调试代码,重点关注线程锁、CRC计算、帧解析和超时控制等关键环节,在真实产线中验证通信稳定性,并利用日志系统进行故障分析与优化。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值