问题 A: 幸运数字III
[
提交
][
状态
][
讨论版
]
题目描述
小李非常喜欢数字4和7,看到一个数字他就想快速计算出因子里面分别有几个4和7,但是智商捉急的他总是要算很久,喜欢编程的你能够帮助他吗?
输入
第一行一个整数n(3<=n<=2^60),表示给定的数字。
输出
两个用空格隔开的数字,分别表示给定数字的因子中4和7的个数。
样例输入
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: 英雄卡
题目描述
小李非常迷恋收集各种干脆面里面的英雄卡,为此他曾经连续一个月都只吃干脆面这一种零食,但是有些稀有英雄卡真的是太难收集到了。后来某商场搞了一次英雄卡兑换活动,只要你有三张编号连续的英雄卡,你就可以换任意编号的英雄卡。小李想知道他最多可以换到几张英雄卡(新换来的英雄卡不可以再次兑换)。
输入
第一行,共一个整数n(1<=n<=10000),表示小李拥有的英雄卡数。
第二行,共n个空格隔开的数字ai(1<=ai<=100000),表示英雄卡的编号。
输出
输出仅有一行,共1个整数,表示小李最多可以换到的英雄卡。
样例输入
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: 最强阵容
题目描述
拿着新换来的英雄卡,小李满心欢喜的准备和同学们PK一下。
他们的游戏规则非常简单,双方把自己的牌绕成一圈,然后指定一个起点,从该张牌开始顺时针方向往后取,谁取出的字符串字典序更小(从左到右开始比较,碰到第一个不一样的字符进行比较,比较规则为a<b<…<z)谁将获得胜利。具体规则可参考样例。虽然现在小李的牌已经很好了,但是你能不能帮他快速算出起始位置,使得他能够派出最强阵容。
输入
第一行n(1<=n<=30000),表示共有n张牌。
第二行共n个用一个空格隔开的小写字母,表示给定的一圈牌起始序列。
输出
仅一个整数,能获得最小字典序字符串的起点位置。如果有多个位置开始的字符串一样,则输出最小的那个位置,且第一个位置从1开始。
样例输入
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: 最强素数
题目描述
小李在你帮助之下轻松战胜了他的同学们,于是满怀恶意的同学出了一个题目来为难小李,作为小李神一样的队友,你又要出力了。
素数41能写成连续6个素数之和:41=2+3+5+7+11+13。
现在要求n以内的素数中,能表示为最多连续素数之和的那个数,如果有多个答案,请输出最大的那个素数。
输入
仅一行,一个整数n(1<=n<=1000000)。
输出
输出就一个整数,为所求的能表示为最多连续素数和的那个素数。
样例输入
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: 小李数星星
题目描述
小李在农村长大,那时候大家喜欢晚饭过后在院子里纳凉,听不懂大人在说什么的小李喜欢抬头看天空,尤其是夏天的夜晚,天上的星星又多又亮。
长大后小李进城打工,每当想家的时他还是喜欢抬头看看天,寻找另一边故乡的记忆。
可是大城市里空气质量太差了,雾霾天气横行,天上能看到的星星也越来越少了。
小李每次用一个正方形去覆盖自己所能看到的星星,随着日子的推移,这个正方形越来越小了,悲伤的小李希望你能告诉他这个正方形的面积。为了让问题变得简单,小李每次只会使用水平放置的正方形来覆盖(不会旋转),具体参照样例解释。
输入
第一行一个整数n,表示星星的数量。
接下来共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: 小李打台球
题目描述
在异乡打拼的小李同志迷上了一款叫斯诺克的台球游戏,而且随着练习的深入,他总是能在某些神奇的时候开启外挂模式,此时小李指哪打哪,直至无球可打。现在小李想让你帮他计算下当他开启外挂模式的时候最多可以取得多少分数。
注意:台面上的球数经常会异于传统斯诺克。
斯诺克比赛的基本规则如下:
一、彩球共分8种颜色,红(1分)、黄(2分)、绿(3分)、棕(4分)、蓝(5分)、粉(6分)、黑(7分)、白(主球,控制白球大其余球)。
二、当台面上有红球的时候你必须先击打一个红球,然后只能击打一个彩球(不包括红球),此时落袋的彩球将会被放回桌面,一直重复该过程。
三、当打完规则二的彩球(不包括红球)发现已经没有红球时,按彩球的分值从高到低将其依次击入袋中。
输入
输入仅有一行,共7个用空格隔开的整数,分别为当前台面上红、黄、绿、棕、蓝、粉、黑球的数目。
输出
输出仅有一行,共1个整数,表示小李可以得到的最高得分。
样例输入
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: 小李发奖金
题目描述
当然打台球只是小李的休闲娱乐活动,对待他的本职工作,他还是非常兢兢业业的。但是小李的老板是个周扒皮,每次都想克扣小李的工资和奖金,甚至制定出非常奇葩的规则。
又到了每年发年终奖的时候了,今年老板的规则是这样的:给你n个数,每次你可以对任意一个数加1,直到所有的数都不相等为止,每加一次都要花费一定数额的费用。为了小李的幸福生活,聪明的你可否帮助小李,让他尽量少扣钱。
输入
第一行n(1<=n<=30000),表示共有n个数。
第二行共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: 小李打怪兽
题目描述
小李对故乡的思念全部化作了对雾霾天气的怨念,这引起了掌控雾霾的邪神的极大不满,邪神派去了一只小怪兽去对付小李,由于这只怪兽拥有极高的IQ,它觉得直接消灭小李太没有难度了,它决定要和小李在智力水平上一较高下。我们可否帮助小李来战胜强大的怪兽呢?
问题是这样的:给定一堆正整数,要求你分成两堆,两堆数的和分别为S1和S2,谁分的方案使得S1*S1-S2*S2的结果小(规定S1>=S2),谁就将获得胜利。
注:S2可以等于0。
输入
第一行n(1<=n<=100),表示共有n个数
第二行共n个用空格隔开的正整数ai(ai<=100),表示给定的一堆正整数。
输出
输出就一个整数,表示 S1*S1-S2*S2 的最小值。
样例输入
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
题目描述
It is nighttime and Joe the Elusive got into the country’s main bank’s safe. The safe has n cells positioned in a row, each of them contains some amount of diamonds. Let’s make the problem more comfortable to work with and mark the cells with positive numbers from 1 to n from the left to the right.
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.
输入
The first line contains integers n, m and k (1≤n≤10
4
, 1≤m,k≤10
9
). The next line contains n numbers. The i-th number is equal to the amount of diamonds in the i-th cell — it is an integer from 0 to 10
5
.
输出
Print a single number — the maximum number of diamonds Joe can steal.
样例输入
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
题目描述
A newspaper is published in Walrusland. Its heading is s1, it consists of lowercase Latin letters. Fangy the little walrus wants to buy several such newspapers, cut out their headings, glue them one to another in order to get one big string. After that walrus erase several letters from this string in order to get a new word s2. It is considered that when Fangy erases some letter, there’s no whitespace formed instead of the letter. That is, the string remains unbroken and it still only consists of lowercase Latin letters.
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?
输入
The input data contain two lines. The first line contain the heading s1, the second line contains the word s2. The lines only consist of lowercase Latin letters (1≤|s1|≤10
4
,1≤|s2|≤10
6
).
输出
If it is impossible to get the word s2 in the above-described manner, print “-1” (without the quotes). Otherwise, print the least number of newspaper headings s1, which Fangy will need to receive the 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;
}