推荐系列:最小与最大[DP+余式定理]
最小与最大
【问题描述】
做过了乘积最大这道题,相信这道题也难不倒你。
已知一个数串,可以在适当的位置加入乘号(设加了k个,当然也可不加,即分成k+1个部分),设这k+1个部分的乘积(如果k=0,则乘积即为原数串的值)对m 的余数(即mod m)为x;
现求x能达到的最小值及该情况下k的最小值,以及x能达到的最大值及该情况下的k的最小值(可以存在x的最小值与最大值相同的情况)。
【输入】
第一行为数串,长度为n 满足2<=n<=1000,且数串中不存在0;
第二行为m,满足2<=m<=50。
【输出】
四个数,分别为x的最小值 和 该情况下的k,以及x的最大值和 该情况下的k,中间用空格隔开。
【样例输入】
4421
22
【样例输出】
0 1 21 0
感觉这题挺好的。
首先你需要知道余式定理: (a*b)mod m = ((a mod m)*(b mod m ))mod m
令f[i][j]表示,前i个数,余数为j时用的k
b[i][j]表示,第i个数到第j个数所形成的数mod m 的值
f[k][s] = min{f[i][j]+1}
其中s=(b[i+1][k]*j)mod m;(余式定理)
怎么理解这个状态转移方程呢?理解各自表示的涵义即可。
b[i+1][k]为,第i+1个数到第k个数所形成的数mod m的值
f[k][s]表示前k个数,余数为s时用的k。状态转移方程即可理解。
输出结果的时候,
因为f中已经存下来能达到所有余数的最少乘号数,所以要输出最大余数,只需要倒着扫一遍,输出最小数只需要顺着扫一遍即可。