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;
}