【题解】8.7夏令营last_test

来源:互联网 发布:淘宝怎么直播呀 编辑:程序博客网 时间:2024/05/16 03:46

1.        

题目名称

约数

负进制

蛋糕

句子

程序名

bri.pas/cpp

negii.pas/cpp

 cake.pas/cpp

sents.pas/cpp

输入文件名

bri.in

negii.in

cake.in

sents.in

输出文件名

bri.out

negii.out

cake.out

sents.out

测试时限

1

1

1

1

本题分值

100

100

100

100

 

第一题  约数

(bri.pas/cpp)

题目描述:

给你一个整数I,求它的所有除数的和。比如I12,和为1+2+3+4+6+12=28

数据范围:

1I1,000,000

输入文件 bri.in:

只一行,一个整数 I

输出文件 bri.out:

只一行,一个整数:I的所有除数之和。

样例:

输入:12

输出:28


【题目分析】

    这道题是纯粹的水题,直接循环就好了,数据量并不大......

【例程】

#include<iostream>

#include<cstdio>

using namespace std;


long long n,ans=0;


int main()

{

freopen("bri.in","r",stdin);

freopen("bri.out","w",stdout);

cin>>n;

for(int i=1;i<=n;++i)

{

if(n%i==0)

ans+=i;

}

cout<<ans<<endl;

}

第二题  负进制

(negii.pas/cpp)

 

题目描述:

学习信息学的人都熟悉 2 进制,但有没有人想过 -2进制!那样的数字就不需要符号了!!

2进制从低位到高位--即从右向左--的位权是124816....

2进制的从右向左的位权当然就是1、-24、-816....

2进制是可以表示任何整数的。如:

1, 110, 111, 100, 101, 11010, 11011, 11000, 11001,...

表示123456789,....

11, 10, 1101, 1100,1111,...

则表示-1,-2,-3,-4,-5,....

现在给你一个十进制的整数n,请求出它的-2进制数。

数据范围:

-2,000,000,000n2,000,000,000

输入文件 negii.in:

只一行,一个十进制整数 n

输出文件 negii.out:

一个-2进制数。如果数字不为0,不能有前导0

样例:

输入

-13

 

输出

110111

从右向左:

1*1 + 1*-2 + 1*4 + 0*-8 +1*16 + 1*-32 = -13    


【题目分析】

    这道题是进制转换类的题目,但我一开始并不会做,是听了同学们分析才恍然大悟。

    其实我们是可以用普通进制转换的做法来做的:不断对-2求mod并将原数除以二,如果余数为1或-1就在那位写1,否则写0。但是如果余数是-1,就要将原数减一再除。


【例程】

#include<iostream>

#include<cstdio>

using namespace std;


int n;

int jl=1;

string st="";



int main()

{

freopen("negii.in","r",stdin);

freopen("negii.out","w",stdout);

cin>>n;

if(n==0)

{

cout<<0<<endl;

return 0;

}

while(n!=0)

{

int tmp=n%-2;

if(tmp==-1)

{

n--;

tmp=1;

}

n/=-2;

char ch = tmp + 48;

st=ch+st;

}

cout<<st<<endl;

}

第三题  蛋糕

(cake .pas/cpp)

 

题目描述:

由于信息学成绩好,Bonnie得到了妈妈奖励的一个蛋糕. 蛋糕是正方形的, 蛋糕的正中间有一个正方形的空洞蛋糕和空洞的中心都是在坐标(0,0). 现在Bonnie打算横的切N, 再竖的切M,问蛋糕最后变成了多少块? 给出一个数组hcuts[1..N ],表示横的切蛋糕时, i刀经过的点是(0, hcuts[i]), 该刀是平行于X轴的直线,切过点(0,  hcuts[i]). 同理: 给出一个数组vcuts[1..M],表示竖的切蛋糕时, j刀经过的点是(vcuts[j],0), 该刀是平行于Y轴的直线,并且经过点(vcuts[i], 0).    我们还给出蛋糕外正方形的边长的一半: cakeLen, 给出蛋糕里面的空洞的正方形的边长的一半: holeLen.

输入:

l      第一行: 两个整数:  cakeLenholeLen.  2<= cakeLen <= 100

    1 <= holeLen  <= cakeLen 1.

l      第二行:两个整数: N 和 M. 表示横的(平行于X轴)切N刀,竖的(平行于Y轴)切M刀。 0 <= N, M <= 50

l      接下来一行有N个整数,则hcuts[ ], 空格分开,第i个整数表示横的切第i刀,它经过点的坐标是:(0, hcuts[i ]. 如果N = 0, 那么该行没有数据。

l      接下来一行有M个整数,则vcuts[ ], 空格分开,第j个整数表示竖的切第j刀,它经过点的坐标是:(vcuts[ j], 0. 如果M = 0, 那么该行没有数据。

 注意:hcuts[ ] 数组里面没有重复的数据,vcuts[ ]也没有重复数据,并且两个数组里面元素的范围都是:[-cakeLen + 1, cakeLen 1

  提示:每次切蛋糕,肯定是把整个蛋糕切开两半,则:不存在,刀不够长而不能把蛋糕完整的切开。

 输出:

一个整数:蛋糕最后变成了多少块?

 样例1:

输入: cake.in

   5   3

   2   1

   1   -4

   1

输出:cake.out

6

如下图所示:

如上图所示:蛋糕的边长是2*5 = 10 空洞的边长是2* 3 = 6

横的切两刀,也就是分别用直线y = 1y = -4 切下去, 竖的切1刀,用直线x = 1切下去。于是最后蛋糕变成了6块,分别用不同的颜色表示。


【题目分析】

    这道题可以用数学方法解;

    我们看如果是竖着切两刀,其块数有2+1块,此时再横着切两刀,就有(2+1)(2+1)块;

    但因为其中又会有空,所以还要减去一部分,减去的就是经过里面的横刀数-1乘上经过里面的竖刀数-1(只要里面有刀切就成立)


【例程】

#include<iostream>

#include<cmath>

#include<cstdio>

using namespace std;


int n,m,clen,hlen;

int jl,jl2;

int k;


int main()

{

freopen("cake.in","r",stdin);

freopen("cake.out","w",stdout);

cin>>clen>>hlen;

cin>>n>>m;

for(int i=0;i<n;++i)

{

cin>>k;

if(abs(k)<=hlen)

++jl;

}

for(int i=0;i<m;++i)

{

cin>>k;

if(abs(k)<=hlen)

++jl2;

}

int ans=(n+1)*(m+1);

int tmp=0;

if(jl>1||jl2>1)

{

tmp=(jl-1)*(jl2-1);

}

ans-=tmp;

cout<<ans<<endl;

return 0;

}

 

第四题  句子

(sents.pas/cpp)

 

题目描述:

明明与可可经常在网上聊天,但最近他们发现父母们可能查看了他们的隐私谈话。因此他们发明了一些加密方法的语言。

所有合法的单词在给定的单词列表中。一个句子由一些合法单词连续组成(没有空格)。每个单词可以出现任意多次。特殊的加密方法是:每个单词在传送之后,它的字母有可能打乱了重新排列。这次加密的代价定义为:加密前的单词和加密后的单词有多少位置上的字母不相同。比如:"abc" 变为 "abc",则代价为0。如果变为"acb""cba""bac"则代价为2。如果变为"bca" "cab"则代价为3

对于接收到的句子,解码成加密前的句子可能有多种方案,但明明和可可知道只有句子的加密总代价最小的方案才是真正的原来的句子。面对这么复杂的加密语言,他们的父母当然看不懂。但不幸的是,他们自己也搞不懂了。他们需要你帮助研究。

任务

对于给定的合法单词列表和加密后的句子,求出由合法单词通过加密形成现在句子的最小代价。如果没有可能,则输出-1

提示:一个单词如果出现多次,每次加密后的单词并不一定相同。

数据范围:

合法单词数:1n50;

每个单词长度:1lenwi50;

句子长度:1lens100;

所有单词和句子中的字符都是小写字母 ('a'-'z') 

输入文件sents.in:

第一行:一个整数 n,表示合法单词个数。

下面 n 行:每行一个字符串,表示一个合法单词。

最后一行:一个字符串,表示加密后的句子。

输出文件sents.out:

只一行,一个整数。

样例:

输入

4

one

two

three

there

neotowheret

答案说明:

"one" -> "neo" 代价为 3

"two" -> "tow" 代价为 2

"three" -> "heret" 代价为 3

"there" -> "heret" 代价为 5

最小代价=3+2+3=8

输出

8

    


【题目分析】

     完全背包......


【例程】

#include<iostream>

#include<algorithm>

#include<cstdio>


#define oo 100000000


using namespace std;


int n ;

string ST ;

string st[1000] ;


int ch1[26] ,

ch2[26] ;


int f[1000] ;


int Check( string test , int i )

{

int sum = 0 ;

int ln = test.size() ;

for ( int k = 0 ; k < 26 ; k ++ )

ch1[k] = ch2[k] = 0 ;

for ( int j = i ; j < i+ln ; j ++ )

{

if ( ST[j] != test[j-i] ) sum ++ ;

ch1[test[j-i]-'a']++;

ch2[ST[j]-'a']++;

//cout<<ST[j]<<"_"<<test[j-i]<<endl;

}

for ( int k = 0 ; k < 26 ; k ++ )

if ( ch1[k]!=ch2[k] ) 

{

//cout<<char(k+'a')<<" " <<ch1[k]<<"_"<<ch2[k]<<endl;

return oo ;

}

//cout<<"yes"<<endl;

//cout << "_"<<test<<"_"<<sum<<endl;

return sum ;

}


int main()

{

freopen ( "sents.in" , "r" , stdin ) ;

freopen ( "sents.out" , "w" , stdout ) ; 

cin >> n ;

for ( int i = 0 ; i < n ; i ++ )

cin >> st[i] ;

cin >> ST ;

f[0] = 0 ;

for ( int i = 1 ; i < 1000 ; i ++ )

f[i] = oo ;

for ( int i = 0 ; i <= ST.size() ; i ++ )

{

for ( int j = 0 ; j <= n ; j ++ )

if ( i+st[j].size() <= ST.size() )

{

f[i+st[j].size()] = min( f[i+st[j].size()] , f[i]+Check(st[j],i));

//cout << i+st[j].size() << "_"<<f[i+st[j].size()]<<endl;

}

}

// cout << ST.size() << endl ;

if ( f[ST.size()] == oo ) cout<<"-1"<<endl ;

else cout<<f[ST.size()] << endl ;

return 0;

}#include<iostream>

#include<algorithm>

#include<cstdio>


#define oo 100000000


using namespace std;


int n ;

string ST ;

string st[1000] ;


int ch1[26] ,

ch2[26] ;


int f[1000] ;


int Check( string test , int i )

{

int sum = 0 ;

int ln = test.size() ;

for ( int k = 0 ; k < 26 ; k ++ )

ch1[k] = ch2[k] = 0 ;

for ( int j = i ; j < i+ln ; j ++ )

{

if ( ST[j] != test[j-i] ) sum ++ ;

ch1[test[j-i]-'a']++;

ch2[ST[j]-'a']++;

//cout<<ST[j]<<"_"<<test[j-i]<<endl;

}

for ( int k = 0 ; k < 26 ; k ++ )

if ( ch1[k]!=ch2[k] ) 

{

//cout<<char(k+'a')<<" " <<ch1[k]<<"_"<<ch2[k]<<endl;

return oo ;

}

//cout<<"yes"<<endl;

//cout << "_"<<test<<"_"<<sum<<endl;

return sum ;

}


int main()

{

freopen ( "sents.in" , "r" , stdin ) ;

freopen ( "sents.out" , "w" , stdout ) ; 

cin >> n ;

for ( int i = 0 ; i < n ; i ++ )

cin >> st[i] ;

cin >> ST ;

f[0] = 0 ;

for ( int i = 1 ; i < 1000 ; i ++ )

f[i] = oo ;

for ( int i = 0 ; i <= ST.size() ; i ++ )

{

for ( int j = 0 ; j <= n ; j ++ )

if ( i+st[j].size() <= ST.size() )

{

f[i+st[j].size()] = min( f[i+st[j].size()] , f[i]+Check(st[j],i));

//cout << i+st[j].size() << "_"<<f[i+st[j].size()]<<endl;

}

}

// cout << ST.size() << endl ;

if ( f[ST.size()] == oo ) cout<<"-1"<<endl ;

else cout<<f[ST.size()] << endl ;

return 0;

}





0 0
原创粉丝点击