9-15考试题目程序作业

然而有素质的我选择把题目也粘在上面,喜欢的同学可以做一下

支付宝
(pay.pas/c/cpp)
题目描述
做完前七次Nescafé 模拟赛之后,你已经欠了一大笔电费。现在收电费的已经把你堵在了家里。当然了,你并不是打算一直拖欠电费的人,你只是如果不能用最少的纸币张数凑出电费金额的话会感到十分不爽。本来这是一件很简单的事,但是你平常很少使用标准的纸币,而是习惯去银行领一本支票簿,在每一张上填上自己喜欢的金额然后把这些东西用作纸币付账,这就使问题变得复杂了起来。现在你知道你一共填写了N种金额的支票,第i 种支票的金额和数目分别是Wi 和Ci,而电费的总额是K。为了尽快把收电费的打发走,你需要写一个程序,帮助你确定使用支票数目最少的支付方案。
输入格式
第一行是一个整数N,表示支票金额的种类数。
第二行是 N 个整数W1, W2, ..., WN,表示支票的金额。
第三行是 N 个整数C1, C2, ..., CN,表示支票的数目。
第四行是一个整数 K,表示电费的金额。
输出格式
第一行输出一个整数 T,表示至少需要使用的支票数目。
第二行按顺序输出 N 个整数U1, U2, ..., UN。其中Ui 表示使用第i 种支票的数目。
如果有多种方案,你只需要输出任意一个。
样例输入
3
2 3 5
2 2 1
10
样例输出
3
1 1 1
数据范围与约定
对于20% 的数据,N≤10,Wi≤500,Ci≤200,K≤2000。
对于 100% 的数据,N≤200,Wi, Ci, K≤20000。

 

解析:二维背包,记录选择方式,注意要完全装满(不装满收电费的回来找你= =)初值除了f[0]=0以外全部maxlongint;

代码

var
        i,j,m,t,n,k:longint;
        p:array[0..202,0..20020] of longint;
        f,w,c:array[0..20202] of longint;

        function min(a,b:longint):longint;
        begin if a<b then exit(a) else exit(b); end;

        procedure mk(x,y,z:longint);
        var i:longint;
        begin
                for i:=k downto y do
                if (f[i]>f[i-y]+x) then
                begin
                        f[i]:=f[i-y]+x;
                        p[z][i]:=p[z][i-y]+x;
                end;
        end;

        begin
                assign(input,'pay.in');
                reset(input);
                assign(output,'pay.out');
                rewrite(output);
                readln(n);
                for i:=1 to n do read(w[i]);
                for i:=1 to n do read(c[i]);
                readln(k);

                fillchar(f,sizeof(f),127);
                f[0]:=0;
                for i:=n downto 1 do
                begin
                        j:=0;
                        while c[i]<>0 do
                        begin
                                t:=min(1<<j,c[i]);
                                mk(t,t*w[i],i);
                                c[i]:=c[i]-t;
                                inc(j);
                        end;
                end;

                writeln(f[k]);
                for i:=1 to n do
                begin
                        write(p[i][k],' ');
                        k:=k-p[i][k]*w[i];
                end;
                close(input);
                close(output); 
        end.

SECHS
(sec.pas/c/cpp)
题目描述
对于给定的正整数N,我们把[1, N]中的整数按照字符串的字典序排序得到N 项数列A(N)。例如,N = 11的时候,A(N) = {1, 10, 11, 2, 3, 4, 5, 6, 7, 8, 9}。二元函数 Q(N, K) 的定义域为N, K∈Z+ 且 N≥K,其值为K 在A(N) 中的位置。例如从上面给出的A(11)中可以看出Q(11, 2) = 4。现在你的任务是,对于给定的正整数 K 和M,求最小的正整数N 满足Q(N, K) = M。
输入格式
仅有一行,包含两个正整数K 和M。
输出格式
输出一个正整数N 表示答案。如果不存在这样的N,输出0。
样例输入 1
12 7
样例输出1
102
样例输入 2
100000001 1000000000
样例输出2
100000000888888879
数据范围与约定
对于30% 的数据,满足M, K≤100。
对于 100% 的数据,满足1≤M, K≤109。

 

解析:先判0,除去之后按位数做

代码(巨短)

var
        i,j,m,n,k:int64;

        begin
                assign(input,'sec.in');
                reset(input);
                assign(output,'sec.out');
                rewrite(output);
                readln(m,k);
                n:=1;
                while n*10<=m do
                n:=n*10;

                i:=n;
                j:=m;

                while i<>0 do
                begin
                        k:=k-(j-i+1);
                        i:=i div 10;
                        j:=j div 10;
                end;

                if (k<0) or (k>0) and (n=m) then begin writeln(0); close(input); close(output); halt; end
                else if k=0 then writeln(m) else
                begin
                        while true do
                        begin
                                n:=n*10;
                                m:=m*10;
                                if k>m-n then
                                k:=k-(m-n)
                                else
                                begin
                                        writeln(n+k-1);
                                        break;
                                end;
                        end;
                end;
                close(input);
                close(output);
        end.

数列操作
(sequence.pas/c/cpp)
题目描述
给定一个长度为?的整数数列?=(?1,?2,…,??),并且可以对这个数列进行一种操作:选择两个正整数?,?(1≤?≤?≤?),将??,??+1,…,??同时加上一或者同时减去一。
再给定一个长度为?的整数数列?=(?1,?2,…,??),要求用最少的操作次数将数列?变成数列?。
输入格式
输入文件名为sequence.in,共三行。
第一行包含一个正整数?。
第二行包含?个整数,表示数列?。
第三行包含?个整数,表示数列?。
输出格式
输出文件名为sequence.out,共一行,包含一个正整数,表示最少需要的操作次数。
样例输入
3
3 4 5
6 7 8
样例输出
3
数据范围与约定
对于40%的数据满足,?≤100,0≤|??|,|??|≤100;
对于80%的数据满足,?≤1,000;
对于100%的数据满足,?≤100,000,0≤|??|,|??|≤1,000,000。

 

这题题干有点问题,显示不出来。大概就是给出当前序列和目标序列,每次将一个区间的所有值加1或减1,输出最少改动次数(详见noip2013火柴排队)

题解:贪心,先分出每一个单独的,正负相同的区间,对每个区间贪心,比前一个低就跳过,比前一个高就加上差值,易证其正确性

代码

var
        a,b,f,d:array[0..156321] of longint;
        ans,k,l,m,n,p:int64;
        i,j:longint; 
        o1,o2:boolean;


        begin
                assign(input,'sequence.in');
                reset(input);
                assign(output,'sequence.out');
                rewrite(output);
                readln(n);
                for i:=1 to n do read(a[i]);
                for i:=1 to n do read(b[i]);
                for i:=1 to n do f[i]:=a[i]-b[i];
                for i:=1 to n do
                begin
                        if ((f[i]>0) and (f[i+1]<=0)) or ((f[i]<0) and (f[i+1]>=0)) then
                        begin
                        inc(l);
                        d[l]:=i;
                        end;
                end;
                d[l+1]:=n;

                for i:=0 to l do
                begin
                        m:=0;
                for j:=d[i]+1 to d[i+1]  do
                begin
                        if m<abs(f[j]) then  inc(p,abs(f[j])-m);
                        m:=abs(f[j]);
                end;
                end;
                writeln(p);
                close(input);
                close(output);
        end.

喜欢就收藏一下吧,vic个人qq:1064864324。加我来一起讨论竞赛题目,交流感想,共同进步

 

转载于:https://www.cnblogs.com/victorslave/p/4811584.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Private Function setdata(num As Integer) As String '数字转换 Select Case num Case 0 setdata = "零" Case 1 setdata = "壹" Case 2 setdata = "贰" Case 3 setdata = "叁" Case 4 setdata = "肆" Case 5 setdata = "伍" Case 6 setdata = "陆" Case 7 setdata = "柒" Case 8 setdata = "捌" Case 9 setdata = "玖" End Select End Function Private Function chang(aaa As Integer) As String '位数转换 Select Case aaa Case 1 chang = "" Case 2 chang = "十" Case 3 chang = "百" Case 4 chang = "千" Case 5 chang = "万" Case 6 chang = "十" Case 7 chang = "百" Case 8 chang = "千" Case 9 chang = "亿" Case 10 chang = "十" End Select End Function Private Sub Form_Activate() '设定文本长度 Text2.MaxLength = 10 Text2.SetFocus End Sub Private Sub Text2_Change() '小写转大写 Dim i As Integer Dim j As Integer Dim myint As Integer Dim myint1 As Integer Dim mydoub As Double Dim mystr As String Dim mystr1 As String Dim mystr2 As String Dim mystr3 As String Dim mystr4 As String Dim money As Long Dim money1 As Integer Dim money2 As Long mystr = Text2.Text myint = InStr(mystr, ".") If myint = 0 Then mystr = Text2.Text Else mystr3 = Right(Text2.Text, Len(Text2.Text) - myint) If mystr3 <> "" Then '转换小数位 mystr4 = Left(mystr3, 1) mystr3 = Right(mystr3, Len(mystr3) - 1) If mystr4 <> "0" Then mystr2 = mystr2 + setdata(Val(mystr4)) + "角" End If If mystr3 <> "" Then mystr4 = Left(mystr3, 1) mystr2 = mystr2 + setdata(Val(mystr4)) + "分" End If End If mystr = Left(Text2.Text, myint - 1) End If j = Len(mystr) For i = 1 To Len(mystr) '转换整数位 money2 = Left(mystr, i) money1 = Right(money2, 1) If money1 = 0 Then If j = 5 Then If Right(mystr1, 1) <> "万" Then mystr1 = mystr1 & "万" Else If Right(mystr1, 1) <> "零" And Right(money, j) > 0 Then mystr1 = mystr1 & "零" End If Else mystr1 = mystr1 & setdata(money1) + chang(j) End If j = j - 1 Next i Text1.Text = mystr1 & "元" & mystr2 '显示大写 End Sub Private Sub Command1_Click() End End Sub
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值