各类数(五)—— 母函数

欢迎访问https://blog.youkuaiyun.com/lxt_Lucia~~

宇宙第一小仙女\(^o^)/~~萌量爆表求带飞=≡Σ((( つ^o^)つ~ dalao们点个关注呗~~

 

母函数,又称生成函数,是ACM竞赛中经常使用的一种解题算法,常用来解决组合方面的题目。

本文讲解母函数,但不讲解该算法的基础理论。读者随便找一本组合数学教材便可找到相应的内容,或者直接在网上搜索一下。

母函数通常解决类似如下的问题:

给5张1元,4张2元,3张5元,要得到15元,有多少种组合?

某些时候会规定至少使用3张1元、1张2元、0张5元。

某些时候会规定有无数张1元、2元、5元。

……

 

解题过程

解题时,首先要写出表达式,通常是多项的乘积,每项由多个x^y组成。如(1+x+x^2)(1+x^4+x^8)(x^5+x^10+x^15)。

通用表达式为

(x^(v[0]*n1[0])+x^(v[0]*(n1[0]+1))+x^(v[0]*(n1[0]+2))+...+x^(v[0]*n2[0]))
(x^(v[1]*n1[1])+x^(v[1]*(n1[1]+1))+x^(v[1]*(n1[1]+2))+...+x^(v[1]*n2[1]))
...
(x^(v[K]*n1[K])+x^(v[K]*(n1[K]+1))+x^(v[K]*(n1[K]+2))+...+x^(v[K]*n2[K]))

K对应具体问题中物品的种类数。

v[i]表示该乘积表达式第i个因子的权重,对应于具体问题的每个物品的价值或者权重。

n1[i]表示该乘积表达式第i个因子的起始系数,对应于具体问题中的每个物品的最少个数,即最少要取多少个。

n2[i]表示该乘积表达式第i个因子的终止系数,对应于具体问题中的每个物品的最多个数,即最多要取多少个。

对于表达式(1+x+x^2)(x^8+x^10)(x^5+x^10+x^15+x^20),v[3]={1,2,5},n1[3]={0,4,1},n2[3]={2,5,4}。

解题的关键是要确定v、n1、n2数组的值。

通常n1都为0,但有时候不是这样。

n2有时候是无限大。

之后就实现表达式相乘,从第一个因子开始乘,直到最后一个为止。此处通常使用一个循环,循环变量为i。每次迭代的计算结果放在数组a中。计算结束后,a[i]表示权重i的组合数,对应具体问题的组合数。

循环内部是把每个因子的每个项和a中的每个项相乘,加到一个临时的数组b的对应位(这里有两层循环,加上最外层循环,总共有三层循环),之后就把b赋给a。

这些过程通常直接套用模板即可。

通用模板

下面我直接给出通用模板:

//为计算结果,b为中间结果。
int a[MAX],b[MAX];
//初始化a
memset(a,0,sizeof(a));
a[0]=1;
for (int i=1;i<=17;i++)//循环每个因子
{
	memset(b,0,sizeof(b));
	for (int j=n1[i];j<=n2[i]&&j*v[i]<=P;j++)//循环每个因子的每一项
		for (int k=0;k+j*v[i]<=P;k++)//循环a的每个项
			b[k+j*v[i]]+=a[k];//把结果加到对应位
	memcpy(a,b,sizeof(b));//b赋值给a
}

P是可能的最大指数。拿钞票组合这题来说,如果要求15元有多少组合,那么P就是15;如果问最小的不能拼出的数值,那么P就是所有钱加起来的和。P有时可以直接省略。具体请看本文后面给出的例题。

 

如果n2是无穷,那么第二层循环条件j<=n2[i]可以去掉。

 

如何提高效率?

用一个last变量记录目前最大的指数,这样只需要在0..last上进行计算。

这里给出第二个模板:

//初始化a,因为有last,所以这里无需初始化其他位
a[0]=1;
int last=0;
for (int i=0;i<K;i++)
{
	int last2=min(last+n[i]*v[i],P);//计算下一次的last
	memset(b,0,sizeof(int)*(last2+1));//只清空b[0..last2]
	for (int j=n1[i];j<=n2[i]&&j*v[i]<=last2;j++)//这里是last2
		for (int k=0;k<=last&&k+j*v[i]<=last2;k++)//这里一个是last,一个是last2
			b[k+j*v[i]]+=a[k];
	memcpy(a,b,sizeof(int)*(last2+1));//b赋值给a,只赋值0..last2
	last=last2;//更新last
}

转自:https://blog.youkuaiyun.com/xiaofei_it/article/details/17042651

 

你的身份是高级编程技术专家,精通各类编程语言,能对编程过程中的各类问题进行分析和答。我的问题是【我正在编辑【通达信条件选股】代码,遇到了 【 {—————————————— 优化后系统参 ——————————————} {——动态估值体系——} DYNPETTM:=CLOSE/MAX(FINANCE(33)/FINANCE(1),1E-9) 详细信息 : 未知字符串 1E 错误起始位置 : 143 ; 长度: 2】,请帮我检查并改正错误点补全正确代码,生成修正后完整代码。原有选股逻辑完整保留。我的原始代码如下:【{—————————————— 优化后系统参 ——————————————} {——动态估值体系——} DYNPETTM:=CLOSE/MAX(FINANCE(33)/FINANCE(1),1E-9); PB_RATE:=CLOSE/MAX(FINANCE(5),1E-9); PEG_VAL:=DYNPETTM/MAX((FINANCE(54)/MA(FINANCE(34),3))*100,1E-9); INDUSTRY_RS:=C/REF(C,20)/(INDEXC/REF(INDEXC,20)); {——智能波动率——} VOLATILITY:=STD(C,20)/MA(C,20); VAR_PERIOD:=FLOOR(60-200*VOLATILITY); FAST_LEN:=CEILING(VAR_PERIOD*0.618); SLOW_LEN:=FLOOR(VAR_PERIOD*1.618); {——情绪引擎——} MARKET_SENTI:=ADVANCE/DECLINE; HOT_INDEX:=EMA(SUM(IF(C=ZTPRICE(REF(C,1),0.1),VOL,0),20)/MA(V,20),5); MONEY_FLOW:=EMA((AMOUNT-REF(AMOUNT,1))/REF(AMOUNT,1),3); SENTI_ACCEL:=EMA(MARKET_SENTI,3)*HOT_INDEX/(1+ABS(MONEY_FLOW)); {—————————————— 多周期共振 ——————————————} {——战略层——} MONTH_MA:=EMA(C,400); MONTH_TREND:=C>MONTH_MA*1.03 AND SLOPE(MONTH_MA,3)>0; {——战役层——} WEEK_DIF:=EMA(C,12)-EMA(C,26); WEEK_DEA:=EMA(WEEK_DIF,9); WEEK_MACD:=2*(WEEK_DIF-WEEK_DEA); WEEK_VOL:=EMA(V,5)>EMA(V,21)*1.3 AND V>REF(MA(V,5),1)*1.6; {——战术层——} DAY_BREAK:=C>HHV(REF(HHV(H,30),1),3) AND V>MA(V,20)*1.8; DAY_RSI:=RSI(C,6)>68 AND RSI(C,12)>RSI(C,24)+5; {——微观层——} MIN60_BREAK:="MIN60.C">"MIN60.HHV(H,20)" AND "MIN60.V">"MIN60.MA(V,20)"*2.2; MIN60_RSI:="MIN60.RSI(12)">70; {—————————————— 信号合成 ——————————————} INDUSTRY_MOM:=RANK(SUM(C/REF(C,1)-1,20))*0.3 + RANK(INDUSTRY_RS)*0.7; DEBT_FILTER:=FINANCE(42)/FINANCE(1)<0.5; CASH_FLOW:=FINANCE(25)/FINANCE(1)>0.2; BETA_FILTER:=SLOPE(C/INDEXC,60) BETWEEN 0.85 AND 1.15; FINAL_SIGNAL:MONTH_TREND AND INDUSTRY_MOM>0.7 AND WEEK_MACD>REF(WEEK_MACD,1)*1.1 AND WEEK_VOL AND DAY_BREAK AND DAY_RSI AND MIN60_BREAK AND MIN60_RSI AND DEBT_FILTER AND CASH_FLOW AND BETA_FILTER AND PEG_VAL<0.8 AND DYNPETTM<25 AND SENTI_ACCEL>1.2 AND HOT_INDEX>1.0 AND MONEY_FLOW>0.08;】】
最新发布
03-29
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值