问题 A: 幸运数字III
题目描述
输入
输出
样例输入
112
样例输出
2 1
提示
112=4*4*7
#include<stdio.h>
typedef long long ll;
int main()
{
ll n;
while(~scanf("%lld",&n)){
ll ans1=0,ans2=0;
if(n==0){
printf("0 0\n");
continue;
}
for(;;){
if(n%4==0){
n/=4;
ans1++;
}else if(n%7==0){
n/=7;
ans2++;
}else{
printf("%lld %lld\n",ans1,ans2);
break;
}
}
}
return 0;
}
问题 B: 英雄卡
时间限制: 1 Sec 内存限制: 128 MB提交: 226 解决: 58
[ 提交][ 状态][ 讨论版]
题目描述
输入
第二行,共n个空格隔开的数字ai(1<=ai<=100000),表示英雄卡的编号。
输出
样例输入
6
3 1 2 4 4 5
样例输出
1
提示
1 2 3三张编号连续,可以换一张,换完后剩下4 4 5,不符合兑换规则,无法继续兑换。
#include<stdio.h>
#include<algorithm>
using namespace std;
int minz(int a,int b,int c)
{
return min(min(a,b),c);
}
int main()
{
int a[100005]={0},n,x,ans=0;
scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%d",&x);
a[x]++;
}for(int i=1;i<=100000;i++){
if(a[i]>=1&&a[i+1]>=1&&a[i+2]>=1){
x=minz(a[i],a[i+1],a[i+2]);
ans+=x;
a[i]-=x;a[i+1]-=x;a[i+2]-=x;
}
}printf("%d\n",ans);
return 0;
}
问题 C: 最强阵容
时间限制: 1 Sec 内存限制: 128 MB提交: 137 解决: 40
[ 提交][ 状态][ 讨论版]
题目描述
他们的游戏规则非常简单,双方把自己的牌绕成一圈,然后指定一个起点,从该张牌开始顺时针方向往后取,谁取出的字符串字典序更小(从左到右开始比较,碰到第一个不一样的字符进行比较,比较规则为a<b<…<z)谁将获得胜利。具体规则可参考样例。虽然现在小李的牌已经很好了,但是你能不能帮他快速算出起始位置,使得他能够派出最强阵容。
输入
第二行共n个用一个空格隔开的小写字母,表示给定的一圈牌起始序列。
输出
样例输入
4
b c a b
样例输出
3
提示
四个位置取出的字符串分别为bcab,cabb,abbc,bbca,显然最小位置是3。
#include<stdio.h>
#include<string.h>
int main()
{
int n;
scanf("%d",&n);
char str[60006],ch[2];
for(int i=0;i<n;i++){
scanf("%s",ch);
str[i]=ch[0];
str[i+n]=ch[0];
}
char ans[30003],temp[30003];
strncpy(ans,str,n);
int cur=1;
for(int i=0;i<n;i++){
strncpy(temp,str+i,n);
if(strcmp(ans,temp)<=0){
continue;
}else{
strcpy(ans,temp);
cur=i+1;
}
}printf("%d\n",cur);
return 0;
}
问题 D: 最强素数
时间限制: 1 Sec 内存限制: 128 MB提交: 59 解决: 12
[ 提交][ 状态][ 讨论版]
题目描述
素数41能写成连续6个素数之和:41=2+3+5+7+11+13。
现在要求n以内的素数中,能表示为最多连续素数之和的那个数,如果有多个答案,请输出最大的那个素数。
输入
输出
样例输入
100
样例输出
41
提示
41=2+3+5+7+11+13
#include<stdio.h>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=1e6+7;
ll x[N],prime[N],cnt=0;
ll sum[N];
void is_prime(int n)
{
for(int i=2;i<=n;i++){
if(x[i]==0){
for(int j=i*2;j<=n;j+=i){
x[j]=2;
}
x[i]=1;
prime[++cnt]=i;
}
}
}
int main()
{
int n,k=0,ans=2,m;
scanf("%d",&n);
is_prime(n);
for(int i=1;i<=cnt;i++){
sum[i]=sum[i-1]+prime[i];
if(x[sum[i]]==1){
k=i;
}
if(sum[i]>n){
m=i;
break;
}
}
int len=k,t=sum[k],tlen=len;
ans=t;
for(int i=1;i<=m;i++){
for(int j=len;i+j<=m;j++){
t=sum[i+j]-sum[i-1];
if(t>n)
break;
if(x[t]==1){
len=max(len,j);
ans=max(ans,t);
}
}
}
printf("%d\n",ans);
return 0;
}
#include<stdio.h>
#include<algorithm>
using namespace std;
const int N=1e6+10;
int prime[N],x[N],cnt,n;
void is_prime()
{
for(int i=2;i<=n;i++){
if(x[i]==0){
for(int j=i*2;j<=n;j+=i){
x[j]=2;
}
x[i]=1;
prime[cnt++]=i;
}
}
}
int main()
{
int len=0,ans=0,m;
scanf("%d",&n);
is_prime();
for(int i=0;i<cnt;i++){
int t=0,tl=0;
for(int j=i;j<cnt;j++){
tl++;
t+=prime[j];
if(t>n) break;
if(x[t]==1&&tl>=len){
ans=t;
len=tl;
}
}
}
printf("%d\n",ans);
return 0;
}
问题 E: 小李数星星
时间限制: 1 Sec 内存限制: 128 MB提交: 206 解决: 58
[ 提交][ 状态][ 讨论版]
题目描述
长大后小李进城打工,每当想家的时他还是喜欢抬头看看天,寻找另一边故乡的记忆。
可是大城市里空气质量太差了,雾霾天气横行,天上能看到的星星也越来越少了。
小李每次用一个正方形去覆盖自己所能看到的星星,随着日子的推移,这个正方形越来越小了,悲伤的小李希望你能告诉他这个正方形的面积。为了让问题变得简单,小李每次只会使用水平放置的正方形来覆盖(不会旋转),具体参照样例解释。
输入
接下来共n行,每行2个正整数(a,b),表示该星星到X轴距离为b,到Y轴距离为a,这些星星只会位于X轴的上方,Y轴的右方。
输入数据保证存在一个合法的正方形 (面积非零)去覆盖这些星星
输出
样例输入
3
1 1
2 1
2 2
样例输出
1
提示
100%的数据,3<=n<=1000, 1<=x<=100000, 1<=y<=100000
#include<stdio.h>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=1000001;
int main()
{
ll minx=N,miny=N,maxx=-1,maxy=-1;
ll n,x,y;
scanf("%lld",&n);
for(int i=0;i<n;i++){
scanf("%lld%lld",&x,&y);
minx=min(minx,x);
miny=min(miny,y);
maxx=max(maxx,x);
maxy=max(maxy,y);
}
ll len=max(maxx-minx,maxy-miny);
ll ans=len*len;
printf("%lld\n",ans);
return 0;
}
问题 F: 小李打台球
时间限制: 1 Sec 内存限制: 128 MB提交: 216 解决: 41
[ 提交][ 状态][ 讨论版]
题目描述
注意:台面上的球数经常会异于传统斯诺克。
斯诺克比赛的基本规则如下:
一、彩球共分8种颜色,红(1分)、黄(2分)、绿(3分)、棕(4分)、蓝(5分)、粉(6分)、黑(7分)、白(主球,控制白球大其余球)。
二、当台面上有红球的时候你必须先击打一个红球,然后只能击打一个彩球(不包括红球),此时落袋的彩球将会被放回桌面,一直重复该过程。
三、当打完规则二的彩球(不包括红球)发现已经没有红球时,按彩球的分值从高到低将其依次击入袋中。
输入
输出
样例输入
2 0 1 0 3 0 2
样例输出
48
提示
台面上共有红球2个、绿球1个、蓝球3个、黑球2个,获得最高分的打法是红-黑-红-黑-绿-蓝-蓝-蓝-黑-黑,共可以获得48分。
保证最后得分不超过2^31-1.
#include<stdio.h>
int main()
{
int a[8];
for(int i=1;i<=7;i++){
scanf("%d",&a[i]);
}for(int i=2;i<=7;i++){
int ans=0;
if(a[i]){
int maxz=0;
for(int i=7;i>=2;i--){
if(a[i]){
maxz=i;
break;
}
}int ans=0;
ans+=(maxz+1)*a[1];
for(int i=2;i<=7;i++){
ans+=i*a[i];
}
printf("%d\n",ans);
return 0;
}
}
if(a[1])
printf("1\n");
else{
printf("0\n");
}
return 0;
}
问题 G: 小李发奖金
时间限制: 1 Sec 内存限制: 128 MB提交: 140 解决: 23
[ 提交][ 状态][ 讨论版]
题目描述
又到了每年发年终奖的时候了,今年老板的规则是这样的:给你n个数,每次你可以对任意一个数加1,直到所有的数都不相等为止,每加一次都要花费一定数额的费用。为了小李的幸福生活,聪明的你可否帮助小李,让他尽量少扣钱。
输入
第二行共n个用空格隔开的非负整数ai(ai<=1000000)。
输出
样例输入
4
1 1 3 2
样例输出
3
提示
让1+1+1+1 = 4,给定的数字变成4,1,3,2。
#include<stdio.h>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=30000;
const int M=1000000;
int a[N],b[M],c[M];
int main()
{
int n;
scanf("%d",&n);
ll ans=0;
for(int i=0;i<n;i++){
scanf("%d",&a[i]);
b[a[i]]++;
}sort(a,a+n);
for(int i=0;i<n;i++){
if(b[a[i]]>1){
for(int j=1;j<=a[n-1]+n;j++){
if(b[j+a[i]]==0){
ans+=j;
b[a[i]]--;
b[j+a[i]]=1;
if(b[a[i]]==1)
break;
}
}
}
}printf("%lld\n",ans);
return 0;
}
问题 H: 小李打怪兽
时间限制: 1 Sec 内存限制: 128 MB提交: 128 解决: 31
[ 提交][ 状态][ 讨论版]
题目描述
问题是这样的:给定一堆正整数,要求你分成两堆,两堆数的和分别为S1和S2,谁分的方案使得S1*S1-S2*S2的结果小(规定S1>=S2),谁就将获得胜利。
注:S2可以等于0。
输入
第二行共n个用空格隔开的正整数ai(ai<=100),表示给定的一堆正整数。
输出
样例输入
4
1 2 3 4
样例输出
0
#include<stdio.h>
#include<algorithm>
using namespace std;
int main()
{
int n;
int sum=0,a[110],dp[10000]={0};
scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%d",&a[i]);
sum+=a[i];
}sort(a,a+n);
int s1,s2,s=sum/2;
for(int i=0;i<n;i++){
for(int j=s;j>=a[i];j--){
dp[j]=max(dp[j],dp[j-a[i]]+a[i]);
}
}
s1=max(dp[s],sum-dp[s]);
s2=sum-s1;
int ans=s1*s1-s2*s2;
printf("%d\n",ans);
return 0;
}
问题 I: Robbery
时间限制: 1 Sec 内存限制: 128 MB提交: 25 解决: 12
[ 提交][ 状态][ 讨论版]
题目描述
Unfortunately, Joe didn't switch the last security system off. On the plus side, he knows the way it works.
Every minute the security system calculates the total amount of diamonds for each two adjacent cells (for the cells between whose numbers difference equals 1). As a result of this check we get an n - 1 sums. If at least one of the sums differs from the corresponding sum received during the previous check, then the security system is triggered.
Joe can move the diamonds from one cell to another between the security system's checks. He manages to move them no more than m times between two checks. One of the three following operations is regarded as moving a diamond: moving a diamond from any cell to any other one, moving a diamond from any cell to Joe's pocket, moving a diamond from Joe's pocket to any cell. Initially Joe's pocket is empty, and it can carry an unlimited amount of diamonds. It is considered that before all Joe's actions the system performs at least one check.
In the morning the bank employees will come, which is why Joe has to leave the bank before that moment. Joe has only k minutes left before morning, and on each of these k minutes he can perform no more than m operations. All that remains in Joe's pocket, is considered his loot.
Calculate the largest amount of diamonds Joe can carry with him. Don't forget that the security system shouldn't be triggered (even after Joe leaves the bank) and Joe should leave before morning.
输入
输出
样例输入
3 2 2
4 1 3
样例输出
2
提示
In the sample Joe can act like this:
The diamonds' initial positions are 4 1 3.
During the first period of time Joe moves a diamond from the 1-th cell to the 2-th one and a diamond from the 3-th cell to his pocket.
By the end of the first period the diamonds' positions are 3 2 2. The check finds no difference and the security system doesn't go off.
During the second period Joe moves a diamond from the 3-rd cell to the 2-nd one and puts a diamond from the 1-st cell to his pocket.
By the end of the second period the diamonds' positions are 2 3 1. The check finds no difference again and the security system doesn't go off.
Now Joe leaves with 2 diamonds in his pocket.
#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
typedef long long ll;
using namespace std;
int main()
{
ll n,m,k,a[10020],minodd=inf,mineven=inf;
scanf("%lld%lld%lld",&n,&m,&k);
for(int i=1;i<=n;i++){
scanf("%lld",&a[i]);
if(i%2){
minodd=min(minodd,a[i]);
}else{
mineven=min(mineven,a[i]);
}
}
if(n%2==0){
printf("0\n");
return 0;
}
ll everyadd,minz,temp=n/2+1;
if(n%2){
minz=minodd;
everyadd=m/(temp);
}
ll ans=min(minz,everyadd*k);
printf("%lld\n",ans);
return 0;
}
问题 J: Newspaper Headline
时间限制: 3 Sec 内存限制: 256 MB提交: 41 解决: 11
[ 提交][ 状态][ 讨论版]
题目描述
For example, the heading is "abc". If we take two such headings and glue them one to the other one, we get "abcabc". If we erase the letters on positions 1 and 5, we get a word "bcac".
Which least number of newspaper headings s1 will Fangy need to glue them, erase several letters and get word s2?
输入
输出
样例输入
abc
xyz
样例输出
-1
#include<bits/stdc++.h>
using namespace std;
#define MAXN 10000
int nxt[MAXN][26];
int main()
{
string S,T;
cin>>S>>T;
memset(nxt,-1,sizeof(nxt));
int N=S.size();
for(int i=0;i<N;i++){
int j=i;
do{
j=(j-1+N)%N;
nxt[j][S[i]-'a']=i;
}while(S[i]!=S[j]);
}
int res=0;
int pos=N-1;
for(int i=0;i<T.size();i++){
int n=nxt[pos][T[i]-'a'];
if(n==-1){
printf("-1\n");
return 0;
}if(n<=pos)res++;
pos=n;
}
printf("%d\n",res);
return 0;
}
#include<stdio.h>
#include<vector>
#include<algorithm>
using namespace std;
char a[10010];
char b[1000010];
vector<int> e[26];
int main(){
scanf("%s%s",a,b);
for(int i=0; a[i]; i++)
e[a[i]-'a'].push_back(i);
int ans=1,now=0;
for(int j=0; b[j]; j++){
int t=b[j]-'a';
if(e[t].empty()){
puts("-1");
return 0;
}
vector<int>::iterator it=lower_bound(e[t].begin(),e[t].end(),now);
if(it==e[t].end()){
ans++;
now=*e[t].begin()+1;
}else
now=*it+1;
}
printf("%d\n",ans);
return 0;
}
本文介绍了2018年宁波市第29-30届信息学竞赛小学组的部分试题,包括问题A到J的详细描述、输入输出格式以及样例解答,涉及算法和逻辑思维的运用。
3575

被折叠的 条评论
为什么被折叠?



