您的位置:首页 > 编程语言 > C语言/C++

【利用同余的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。

=====================================

==========================

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.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: