肇庆学院"菜鸟杯"程序设计竞赛2019(同步赛)部分解题(二)

H-你相信爱情吗?

链接:https://ac.nowcoder.com/acm/contest/3402/H
来源:牛客网

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld

题目描述

    牛郎与织女的故事想必大家都耳熟能详吧,织女真的太爱牛郎了,为了和牛郎在一起,不惜下凡与天庭作对,最后他们俩个还是被硬生生的分离开。织女有一天突然想,要是牛郎不爱她了她得怎么办,由此,织女想考验一下牛郎到底爱不爱她。考验如下:一开始,牛郎和织女在同一个星球上的同一个位置n上,这颗星球上的钻石均匀连续分布在这一星球赤道上;赤道上分布了n个位置,编号为连续的1~n,其中每个位置都放置有一个钻石,总共n个钻石。织女给牛郎一些条件考验限制:
1、牛郎每次只能顺时针移动m步(n往1的方向移动就是顺时针)。
2、牛郎与织女相见后把收集到的钻石给织女。
3、织女要拿到n个钻石。
NOTE:牛郎和织女一开始都在n的位置,织女会一直在n位置等牛郎,牛郎每次结束移动时到达新的位置,都会把这个位置的钻石收集起来,而中间经过的位置不能收集。
    牛郎是个执着的人,他会一直走到取完n个钻石,如果永远取不完就输出-1。问:牛郎能不能完成考验?

输入描述:

第一行一个整数t代表有t个测试样例(1≤t≤100000)
接下来t行,每行俩个整数n和m,如题面所示,1≤n,m<1e18,m≤n;

输出描述:

牛郎若能完成考验就输出最小移动次数,不能就输出-1。
示例1

输入

复制
1
5 2

输出

复制
5

说明

牛郎分别收集钻石的位置的次序为2 -> 4 -> 1 -> 3 -> 5,刚好到达织女的位置给她n=5颗钻石,移动了5次完成了考验



解题思路:
这道题就是考察n和m之间的最大公因子是不是1
如果是1,那么就能达成目标(因为这样不会提前到达n这个终点)
如果不是1,那么在过程中就会提前到达n
而且如果能够成功,那么他的周期也一定是n,因为这样就是n的整倍数,再次出发也只会重复上一次的路径

代码如下:
 1 #include<bits/stdc++.h>
 2 #include<cstdio>
 3 #include<cstdlib>
 4 using namespace std;
 5 
 6 const int maxn=105;
 7 typedef long long ll;
 8 ll n,t,m;
 9 
10 long long int gcd(long long int a,long long int b)
11 {
12      return b?gcd(b,a%b):a;
13  }
14 
15 
16 int main()
17 {
18     while(cin>>t)
19     {
20         while(t--)
21         {
22             cin>>n>>m;
23             ll c=gcd(n,m);
24             if(c!=1)
25                 cout<<"-1"<<endl;
26             else
27                 cout<<n<<endl;
28         }
29     }
30     return 0;
31 }

J-试试划水

链接:https://ac.nowcoder.com/acm/contest/3402/J
来源:牛客网

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld

题目描述

    师兄猜你看的第一道题是这道哈哈哈。没错,师兄给你送福利了,这道题你只需要呆萌呆萌的把下面的代码交上去就行了,师兄是好人【坏笑】。

#include<stdio.h>

#include<string.h>
char ch[100000+5];

int main()

{    

    int t;

    scanf("%d",&t);

    while(t--) { 

        int len,ans=0;    

        scanf("%s",ch);  

        len=strlen(ch);

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

           for(int j=i+1;j<len;j++)

               for(int k=j+1;k<len;k++)    

                  if(ch[i]=='Z'&&ch[j]=='Q'&&ch[k]=='U')        

                      ans++;  

         printf("%d\n",ans);

    }

    return 0;

}


输入描述:

第一行一个整数t代表有t组测试用例,0≤t≤100。

接下来t行,输入一个仅包含'Z','Q'和'U'三种字符的字符串s。( 0<|s|≤100000,|s|为字符串s的长度)

输出描述:

每行一个整数表示代码中ans的值。

示例1

输入

复制
2
ZQUZQU
ZQUZQUZQU

输出

复制
4
10

备注:

TLE了吧【奸笑】,师兄太坏了,不行,这样不好。这道主要锻炼你快速读懂别人代码的能力,好好理解这段代码,想想怎么优化吧。

 

解题思路:

这道题先做个预处理,先从头到尾扫一遍,记录一下Z出现次数的前缀和

然后再从后向前扫一遍,记录一下U出现次数的后缀和

那么最后再扫一遍Q,以每一个Q作为分割点,它前面的Z的个数*他后面U的个数,就是能够组成ZQU的个数

代码如下:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 
 4 const int maxn=1000050;
 5 typedef long long ll;
 6 int n;
 7 
 8 int znum[maxn];
 9 int unum[maxn];
10 
11 
12 int main()
13 {
14 
15     cin>>n;
16     while(n--)
17     {
18         memset(znum,0,maxn);
19         memset(unum,0,maxn);
20         ll ans=0;
21         string str;
22         cin>>str;
23         if(str[0]=='Z')
24             znum[0]=1;
25         for(int i=1; i<str.size(); ++i)
26         {
27             if(str[i]=='Z')
28             {
29                 znum[i]=znum[i-1]+1;
30             }
31             else
32             {
33                 znum[i]=znum[i-1];
34             }
35         }
36         if(str[str.size()-1]=='U')
37             unum[str.size()-1]=1;
38         for(int i=str.size()-2; i>=0; --i)
39         {
40             if(str[i]=='U')
41             {
42                 unum[i]=unum[i+1]+1;
43             }
44             else
45             {
46                 unum[i]=unum[i+1];
47             }
48         }
49         for(int i=0; i<str.size(); ++i)
50         {
51             if(str[i]=='Q')
52             {
53                 ans+=(ll)(znum[i-1]*unum[i+1]);
54             }
55         }
56         cout<<ans<<endl;
57     }
58 
59     return 0;
60 }

K-钟Sir的任务

链接:https://ac.nowcoder.com/acm/contest/3402/K
来源:牛客网

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld

题目描述

    钟Sir最近迷上一种排列交换游戏,游戏规则是这样的:
由1~n的n个互不相同的整数,按任意顺序组成的一个序列,称为1~n的一个排列。(如:[1,3,2]是一个排列,但[1,2,2][1,3,4]不是一个排列)
对于给定的排列,每次操作可以交换位置i和i+1上的元素(1≤i<n,显然一共存在n-1种操作),但每种操作最多执行一次,操作次序不限(显然最多执行n-1次操作,当然也可以选择不操作)。
    问在不违反游戏规则的前提下,能够得到的字典序最小的排列是什么?(如:[1,2,3]字典序小于[1,3,2]) 
    钟Sir觉得一定要玩t场游戏,才能够体现他的强悍实力,但是钟Sir是人不是神仙来的,没办法一口气玩t场游戏(还会死很多脑细胞的),所以钟Sir想让你写一个程序来帮助他。

输入描述:

第一行是一个整数t(1<=t<=100),表示游戏场数。
接下来对每场游戏有两行描述,
第一行是一个整数n(1<=n<=100),表示排列的长度,
第二行包含n个整数,表示给定的1~n的一个排列。

输出描述:

输出在不违反游戏规则的前提下,能够得到的字典序最小的排列。
示例1

输入

复制
4
5
5 4 1 3 2
4
1 2 4 3
1
1
4
4 3 2 1

输出

复制
1 5 2 4 3 
1 2 3 4 
1 
1 4 3 2

说明

教练试玩第一场游戏后,建议你这样操作
5 4 1 3 2 -> 5 4 1 2 3 -> 5 1 4 2 3 -> 1 5 4 2 3 -> 1 5 2 4 3

解题思路:
这道题数据量不大,暴力从后往前扫n遍就能得到正确答案了
代码如下:
 1 #include<bits/stdc++.h>
 2 #include<cstdio>
 3 #include<cstdlib>
 4 using namespace std;
 5  
 6 const int maxn=105;
 7 typedef long long ll;
 8 int n;
 9  
10 int num[maxn];
11 bool did[maxn];
12  
13 int main()
14 {
15     while(cin>>n)
16     {
17         while(n--)
18         {
19             memset(did,0,maxn);
20             memset(num,0,maxn);
21             int m;
22             cin>>m;
23             for(int i=0; i<m; ++i)
24             {
25                 cin>>num[i];
26             }
27             for(int j=0; j<m; ++j)
28             {
29                 for(int i=m-1; i>=1; --i)
30                 {
31                     if(num[i]<num[i-1]&&!did[i])
32                     {
33                         int temp=num[i];
34                         num[i]=num[i-1];
35                         num[i-1]=temp;
36                         did[i]=true;
37                     }
38                 }
39             }
40             for(int i=0; i<m; ++i)
41             {
42                 if(i==0)
43                     cout<<num[i];
44                 else
45                     cout<<" "<<num[i];
46             }
47             cout<<endl;
48         }
49     }
50     return 0;
51 }

 

L-JAJA_Xin的小心思

链接:https://ac.nowcoder.com/acm/contest/3402/L
来源:牛客网

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld

题目描述

    快放寒假了,虽然时间还早,但JAJA_Xin已经准备着回家了。他只有一个行李箱,行李箱的容积为m。但是他的行李又很多,所以他去网购了n个压缩袋,并把他的行李分装成了n个袋子,第i个装好的袋子有初始体积ai,压缩后的体积为bi,但JAJA_Xin比较懒,他希望能尽量少压缩几个袋子就把所有行李装进行李箱,现已知所有的ai和bi,他至少要压缩几个袋子才能把行李装进行李箱?
    一顿sao操作之后,他算好了要压缩几个袋子,jx队长从背后拍了一下他的肩:“怎么,想溜了?乖乖留下集训吧!”

输入描述:

多测试用例,保证 ∑n≤10
7

每组用例的第一行包含两个整数n和m(1≤n≤10
5
,1≤m≤10
9
)。
接下来输入有n行,第i行有两个整数ai和bi(1≤ai,bi≤10
9
, bi<ai)。

输出描述:

请输出需要压缩几个袋子。
如果无法装进行李箱,请输出-1。
示例1

输入

复制
3 10
5 2
6 4
4 3

输出

复制
2

说明

JAJA_Xin可以压缩第一和第二个袋子,因此在这些压缩之后,大小之和将2+4+4=10≤10。请注意,压缩任何单独一个袋子不足以把所有行李都装进行李箱(例如,压缩第三个袋子,大小之和5+6+3=14>10)
示例2

输入

复制
3 8
5 3
6 4
4 2

输出

复制
-1

说明

JAJA_Xin压缩所有的袋子,大小之和将3+4+2=9>8,无法装进行李箱。
解题思路:
没什么花头,就是挑前后差异最大的来进行压缩,同时进行比对
要注意一些特殊情况的判断,就是压缩完也装不进去的情况

代码如下:
 1 #include<bits/stdc++.h>
 2 #include<cstdio>
 3 #include<cstdlib>
 4 using namespace std;
 5 
 6 const int maxn=100005;
 7 typedef long long ll;
 8 int n,m;
 9 
10 
11 int main()
12 {
13 
14     while(cin>>n>>m)
15     {
16         int a,b,ans=0;
17         ll tot=0,preweight=0;
18         vector<int> cut;
19         for(int i=0;i<n;++i)
20         {
21             scanf("%d%d",&a,&b);
22             tot+=b;
23             preweight+=a;
24             cut.push_back(a-b);
25         }
26         sort(cut.begin(),cut.end());
27         if(tot>m)
28             cout<<"-1"<<endl;
29         else
30         {
31             for(int i=cut.size()-1;i>=0;--i)
32             {
33                 if(preweight<=m)
34                     break;
35                 else
36                 {
37                     preweight-=cut[i];
38                     ans++;
39                 }
40             }
41             cout<<ans<<endl;
42         }
43     }
44     return 0;
45 }
 
            
           
 

猜你喜欢

转载自www.cnblogs.com/bethebestone/p/12115872.html
今日推荐