【利用同余的DP】符文之语(chars. pas/c/cpp)
2011-11-07 08:08
316 查看
符文之语(chars. pas/c/cpp)
【题目描述】
当小FF来到神庙时,神庙已经破败不堪了。但神庙的中央有一个光亮如新的石台。小FF走近石台,发现石台上有一个数串,而数串的上方刻着一串古老的符文之语。精通古符文之语的小FF不费吹灰之力就读懂了文章的意思,其大意是:对于石台上的一串数字,你可以在适当的位置加入乘号(设加了k个,当然也可不加,即分成k+1个部分),设这k+1个部分的乘积(如果k=0,则乘积即为原数串的值)对m的余数(即mod m)为x;现求x能达到的最小值及该情况下k的最小值,以及x能达到的最大值及该情况下的k的最小值(可以存在x的最小值与最大值相同的情况)。小FF还知道,如果他找到了正确的答案,那么就可以通往神庙的下层了。但这个问题似乎不太好解决,小FF就找到了你,并答应找到财宝以后和你二八分(当然你拿二……)。
【输入格式】
第一行为数串,且数串中不存在0;
第二行为m。
【输出格式】
四个数,分别为x的最小值和该情况下的k,以及x的最大值和该情况下的k,相邻两个数之间用一个空格隔开。
【输入样例】
4421
22
【输出样例】
0 1 21 0
【数据范围】
对于30%的数据:2≤字符串长度L≤50。
对于100%的数据:2≤字符串长度L≤1000;2≤m≤50。
=====================================
==========================
【题目描述】
当小FF来到神庙时,神庙已经破败不堪了。但神庙的中央有一个光亮如新的石台。小FF走近石台,发现石台上有一个数串,而数串的上方刻着一串古老的符文之语。精通古符文之语的小FF不费吹灰之力就读懂了文章的意思,其大意是:对于石台上的一串数字,你可以在适当的位置加入乘号(设加了k个,当然也可不加,即分成k+1个部分),设这k+1个部分的乘积(如果k=0,则乘积即为原数串的值)对m的余数(即mod m)为x;现求x能达到的最小值及该情况下k的最小值,以及x能达到的最大值及该情况下的k的最小值(可以存在x的最小值与最大值相同的情况)。小FF还知道,如果他找到了正确的答案,那么就可以通往神庙的下层了。但这个问题似乎不太好解决,小FF就找到了你,并答应找到财宝以后和你二八分(当然你拿二……)。
【输入格式】
第一行为数串,且数串中不存在0;
第二行为m。
【输出格式】
四个数,分别为x的最小值和该情况下的k,以及x的最大值和该情况下的k,相邻两个数之间用一个空格隔开。
【输入样例】
4421
22
【输出样例】
0 1 21 0
【数据范围】
对于30%的数据:2≤字符串长度L≤50。
对于100%的数据:2≤字符串长度L≤1000;2≤m≤50。
=====================================
==========================
var st:ansistring; m,st_l:longint; f:Array[0..1000,0..50]of longint; dist:array[0..1000,0..1000]of longint; a:array[1..1000]of longint; procedure init; begin assign(input,'chars.in'); assign(output,'chars.out'); reset(input); rewrite(output); end; procedure terminate; begin close(input); close(output); halt; end; procedure main; var i,j,k:longint; begin readln(st); st_l:=length(st); readln(m); fillchar(f,sizeof(f),$ff); dist[1,0]:=0; for i:=1 to st_l do for j:=i to st_l do begin dist[i,j]:=(dist[i,j-1]*10+ord(st[j])-48)mod m; end; f[0,1]:=0; for i:=1 to st_l do for j:=i-1 downto 0 do for k:=0 to m do if f[j,k]<>-1 then begin if f[i,(k*dist[j+1,i])mod m]=-1 then f[i,(k*dist[j+1,i])mod m]:=f[j,k]+1 else if f[i,(k*dist[j+1,i])mod m]>f[j,k]+1 then f[i,(k*dist[j+1,i])mod m]:=f[j,k]+1; end; for i:=0 to m do if f[st_l,i]<>-1 then begin write(i,' ',f[st_l,i]-1,' '); //减1的原因是开始按只有一段的时候按的是1来算得.. break; end; for i:=m-1 downto 0 do if f[st_l,i]<>-1 then begin write(i,' ',f[st_l,i]-1); break; end; end; begin init; main; terminate; end.
相关文章推荐
- 【区间DP】不老的传说(spring.cpp/pas)
- 【DP,lcs问题】最短回文串(palindrome.pas/c/cpp)
- 4、物流运输(trans.pas/c/cpp) 单源最短路+dp
- MZ test17# NOIP模拟题 # T2 第2题 最优时间表(sche.pas/cpp) [key.DP]
- 利用动态规划(DP)解决 Coin Change 问题
- 【动规】【120817测试】【JSOI2007夏令营考试】题2:考验(b.pas/c/cpp)
- 2012_p4 文化之旅 (culture.cpp/c/pas)
- 编辑距离(edit.c/cpp/pas)
- 传球游戏(ball.pas/c/cpp)
- 利用opencv自带detectpeople.cpp进行行人检测
- HDOJ 1755 - A Number Puzzle 排列数字凑同余,状态压缩DP
- 【斐波那契的一个形式】古代人的难题( puzzle.pas/c/cpp)
- 2018.01.26【NOIP普及组】模拟赛D组——家族(family.pas/cpp)
- 时间计算(heaven.pas/cpp)
- 【usaco2013 mar】灌溉农田(irrigation.pas/cpp/c)//2018.1.28
- 【打表】数页码 count.pas/c/cpp
- mm.cpp/c/pas
- 【记忆化】能量项链(energy.pas/c/cpp)
- 【模拟 计算几何】连线游戏 lines.pas/c/cpp
- 【最短路】逃离遗迹 escape.pas/c/cpp