H-你相信爱情吗?
链接:https://ac.nowcoder.com/acm/contest/3402/H
来源:牛客网
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述
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。
说明
牛郎分别收集钻石的位置的次序为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++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述
#include<stdio.h>
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的值。
备注:
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++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述
由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的一个排列。
输出描述:
输出在不违反游戏规则的前提下,能够得到的字典序最小的排列。
说明
教练试玩第一场游戏后,建议你这样操作
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++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述
一顿sao操作之后,他算好了要压缩几个袋子,jx队长从背后拍了一下他的肩:“怎么,想溜了?乖乖留下集训吧!”
输入描述:
多测试用例,保证 ∑n≤107
;5
每组用例的第一行包含两个整数n和m(1≤n≤10
,1≤m≤109
)。9
接下来输入有n行,第i行有两个整数ai和bi(1≤ai,bi≤10
, bi<ai)。
输出描述:
请输出需要压缩几个袋子。
如果无法装进行李箱,请输出-1。
解题思路:
没什么花头,就是挑前后差异最大的来进行压缩,同时进行比对
要注意一些特殊情况的判断,就是压缩完也装不进去的情况
代码如下:
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 }