2017.09.09【NOIP 普及组】模拟赛C组

T1

题目描述

给出两个数a; b,每次操作可以把a + 1 或把a * 2
问至少多少次操作可以使得a = b

输入

一行两个数a; b

输出

一行一个数ans,表示至少多少次操作可以使得a = b

思路:

倒推。
如果 b mod 2=1 则 做+1操作,反之,做*2操作,直到a=b。

代码:

var x,y,ans:longint;
begin
  assign(input,'dis.in');
  assign(output,'dis.out');
  reset(input);
  rewrite(output);
  read(x,y);
  while y div 2>=x do
  begin
    if y mod 2=1 then inc(ans);
    y:=y div 2; inc(ans);
  end;
  ans:=ans+y-x;
  write(ans);
  close(input);
  close(output);
end.

T2

题目描述

Bessie 在社区大学上电脑课,她最近对于进制数非常感兴趣。
回想一下,一个数被写成B 进制,那么这个数从右到左美味表示1;B;B2;B3, 如此下去。例如,在我们所熟悉的十进制系统下,我们用每位数字分别表示1,10,100,1000,以此类推。如果数字1234 被理解成10 进制,那么它其实应该表示的是1(1000) + 2(100) + 3(10) + 4(1)。如果相同的数字被理解成5 进制,那么它意味着1(125) + 2(25) + 3(5) + 4(1),转换成十进制是19.Bessie 注意到如果进制增加,相同数字串表示的值也增大;比如,1234 在7 进制下的值比1234 在6 进制下的值要大。
当在B 进制下写数字的时候,每位数字的范围都是0..B-1,就比如在十进制下每位数的范围是0..9,在5 进制下是0..4. 考虑进制数大于10 是完全可能的。计算机科学家们常常使用16 进制,A..F 分别表示值10..15. 例如,BEEF 在16 进制下对应11(4096) + 14(256) + 14(16) + 15,对应10 进制下的48879.
Bessie 被”进制数可以大于10”这个概念所深深地迷住。她拿过一个数字N 并且在X 进制和Y 进制两个进制下分别写出,X 和Y 的范围是10..15,000. 有趣的是,在每种情况下,她拿到一个有3 个数字的数字串,每位数字只有0..9。不幸的是,由于Bessie 记性很差,她现在已经忘记了N,X,和Y!给两个3 位数字,请帮助她找出使用过的X 和Y。
请注意由于X 和Y 的潜在大小,一个穷竭搜索所有可能性的程序会超时(有近乎15; 0002 的可能性!),这个程序不会拿到满分

输入

输入文件以整数K 开始;然后接下来有K 行,每行都是一个测试案例。每个测试案例包含两个3 位数字。第一个数字N 被写成X 进制,第二个数被写成Y 进制(N,X 和Y 对于每个测试案例都可能不同)

输出

你个输出应该包含K 行,每个测试案例都是一行。每行这个测试案例对应的X 和Y,用空格隔开。
对于每个测试案例,保证有唯一的答案

代码:

var a,b:array [1..3] of longint;
    num:array [10..15000,0..3] of longint;
    i,j,k,a1,b1,t,r:longint;
procedure init;
begin
  assign(input,'whatbase.in');
  assign(output,'whatbase.out');
  reset(input);
  rewrite(output);
  read(k);
  for i:=10 to 15000 do
  begin
    num[i,1]:=1;
    for j:=2 to 3 do num[i,j]:=num[i,j-1]*i;
  end;
end;
procedure get;
begin
  a[1]:=a1 div 100; a[2]:=a1 mod 100 div 10; a[3]:=a1 mod 10;
  b[1]:=b1 div 100; b[2]:=b1 mod 100 div 10; b[3]:=b1 mod 10;
end;
function find(l,r,dep:longint):longint;
var mid,o:longint;
begin
  while ldo
  begin
    mid:=(l+r) div 2;
    o:=b[1]*num[mid,3]+b[2]*num[mid,2]+b[3]*num[mid,1];
    if o=dep then exit(mid) else if o>dep then r:=mid  else l:=mid+1;
  end;
  exit(0);
end;

begin
  init;
  for i:=1 to k do
  begin
    read(a1,b1);
    for j:=10 to 15000 do
    begin
      get;
      r:=a[1]*num[j,3]+a[2]*num[j,2]+a[3]*num[j,1];
      t:=find(10,15000,r);
      if t<>0 then writeln(j,' ',t);
      if t<>0 then break;
    end;
  end;
  close(input);
  close(output);
end.

T4

题目描述

就像每个人都会遇到的问题一样,贝西忘了在cowtube 上的口令。不过,她还记着一些关于口令的信息。首先,她确定口令由小写字母组成,长度为L。其次,这个密码是由几个单词组合而成的。贝西一共认识N 个单词,每个单词长度都在1 到20 之间,由小写字母组成。最后,贝西还记得口令上一些位置的字母,她会尽量提供记住的部分,如果有些位置上的字母不记得了,就用?代替。给定贝西记得的口令片段和她认识的单词列表,请恢复出她的口令,如果完全符合条件的口令不止一个,输出按照字典序排在最前面的那个。

输入

第一行:两个用空格分开的整数:L 和N,1≤L≤1000,1≤N≤1000
第二行:一个L 长的字符串,代表口令P
第三行到N+2 行:第i+2 有一个字符串W_i,表示贝西认识的第i 个单词W_i

输出

第一行:一个字符串,表示符合条件的,在字典序下最靠前的口令

思路:

背包。
把字符串抽象成背包。

代码:

#include  
#include  
#include  
#include  
using namespace std;  
const int MAXN=1005;  
string a[MAXN],f[MAXN];  
int l,n;  
string Min(string a,string b)  
{

    return aint main()  
{

    int i,j,k;  
    scanf("%d%d",&l,&n);  
    for(i=0; i<=n; i++)
    {

        cin>>a[i];  

    }  
    for(i=1; i<=l; i++)
    {

        for(j=1; j<=n; j++)
        {

            int l=a[j].length();  
            if(l>i||(f[i-l]==""&&i-l!=0)) continue;      
            for (k=i-l+1; k<=i; k++)
            {

                if(a[0][k-1]!='?'&&a[0][k-1]!=a[j][k-i+l-1])    break;  

            }  
            if(k==i+1)
            {

                if(f[i]=="") f[i]=f[i-l]+a[j];  
                else         f[i]=Min(f[i],f[i-l]+a[j]);  

            }  

        }

    }  
    cout<return 0;  
}  

你可能感兴趣的:(题解,jzoj)