靓仔的第一篇博客。
本人ACM菜鸟+新手,因此这篇博客更多的是作为笔记的作用,记录一下自己打训练来的成果和心路历程(其实是和鸟宝吹水说要写博客)。
以后不知道还会不会写(懒
---------------------------------------------------------------------------------------------------
A. Nastia and Nearly Good Numbers
题意: 大概就是给你两个数A和B, 要求你输出3个数 X,Y,Z(输出之前要先输出YES)。 其中X+Y=Z,并且X和Y可以被A整除(称之为nearly good 的数),Z可以被A*B整除(称之为good 的数)。
如果找不到X、Y、Z,就输出 NO。
输入范围: 1< = A,B<= 1e6
输出范围: 1<=X,Y,Z<=1e18
注意:题目中的X和Y(nearly good) 只要被A整除就可以,被B整除也可以。(最开始我理解错题意,将A==B视为错误的情况,WA了11次.............)。
根据题意输入A和B,我们可以直接输出 A*(B-1)、A*(B+1)和 2 *A*B 就可以了。
由题目的输出限制条件可以知道,如果B等于1,那么会输出0,不符合题意,因此B==1就是错误条件。
代码如下:
#include<bits/stdc++.h>
#define endl '\n'
#define ll long long
using namespace std;
int main(){
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
int t;cin>>t;
while(t--){
ll a,b;cin>>a>>b;
if(b==1){
cout<<"NO"<<endl;
continue;
}
cout<<"YES"<<endl;
cout<<a*(b-1)<<' '<<a*(b+1)<<' '<<2*a*b<<endl;
}
}
---------------------------------------------------------------------------------------------------
B. Nastia and a Good Array
题意:给你N个数组成的数组,要求你最终通过变换,让这个数组最终每个相邻的数之间的最大公约数为1,即gcd(ai,aj)= 1 ,其中 | i - j | =1。
变换的规则:选定2个数,ai和aj,1<=i,j<=N,可以将ai和aj变更为任意的x和y,只要保证min(ai,aj)= min(x ,y) ,也就是改变这两个数时只要保证其中最小的数字不改变就可以了。
输入:T,表示有T组样例,然后是N和N个数字。1<= ai <= 1e9 (1<=i<=N)。
输出:输出操作次数num,接下来的num行,每行输出四个数,分别是 i ,j,x,y,也就是你要变换的两个数在数组中的下标以及变换后的数字x和y。
解题思路: 最开始我想的很复杂,但是听了鸟宝的思路后发现有一种更简单的写法(鸟宝,我的鸟宝)。
举个栗子: 数组 9 、6、3、11、15。根据变换的规则要求最小的数字不变,我可以将数组变成这样:3、4、3、4、3。 这样就保证了每两个相邻的数字之间是互质的,并且操作次数可以稳定在N-1次。
非常巧妙和聪明的写法,这样写可以保证每次输出时间复杂度控制在O(n),我只要找到最小的数的下标,然后从这个数到下标为1的数,每次交替输出min+1,min和min,min就可以了。同理,在从最小的数到下标为N的数,每次交替输出min,min+1和min,min。(可能有更好的解法,不过这个简单。)
代码如下:
#include<bits/stdc++.h>
#define endl '\n'
#define ll long long
using namespace std;
int main(){
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
int t;cin>>t;
while(t--){
int n;cin>>n;
ll minn= 0x7f7f7f7f;
int note=1;
ll tmp=0;
for(int i=1;i<=n;i++){
cin>>tmp;
if(tmp<minn){
minn=tmp;
note=i;
}
}
cout<<n-1<<endl;
int check=1;
// 输出前面的
// check用来交替输出 x和y
for(int i=note-1;i>=1;i--){
cout<<i<<' '<<note<<' ';
if(check%2==0)cout<<minn<<' '<<minn<<endl,check++;
else cout<<minn+1<<' '<<minn<<endl,check++;
}
// 输出后面的
check=1;
for(int i=note+1;i<=n;i++){
cout<<note<<' '<<i<<' ';
if(check%2==0)cout<<minn<<' '<<minn<<endl,check++;
else cout<<minn<<' '<<minn+1<<endl,check++;
}
}
}
---------------------------------------------------------------------------------------------------
C. Nastia and a Hidden Permutation
大意:这是一道交互题,类似于你给电脑提问,电脑给你回答,你根据回答来判断出答案这种(不太严谨的描述)。
我也是第一次做这种题目,一开始连题意都没看懂,后面去看了别的大佬的题解才搞懂了这道题。
要注意的是,题目要求使用 fflush(stdout) or cout.flush() 来刷新缓存区以免输出出现问题,这里也可以使用 cin.ignore()来达到同样的效果。
这题确实超出了我的能力范围,因此这里就不描述题意和解释了,直接放出大佬题解的链接来吧。
大佬的题解:(27条消息) Codeforces #720 div2 A~E题解_月阁-CSDN博客
AC代码:
#include<bits/stdc++.h>
#define endl '\n'
#define ull unsigned long long
using namespace std;
const int N=1e4+7;
int n,ar[N];
int ask(int i,int j,int t,int x){
cout<<"?"<<' '<<t<<' '<<i<<' '<<j<<' '<<x<<endl;
int ans;cin>>ans;
return ans;
}
void solve(){
cin>>n;
int note=-1;
for(int i=1;i<=n;i+=2){
int j=i%n+1;
int ans=ask(i,j,1,n-1);
if(ans==n){
note=j;break;
}
else if(ans==n-1){
if(ask(j,i,1,n-1)==n){
note=i;break;
}
}
}
for(int i=1;i<=n;i++){
if(i==note){
ar[i]=n;
continue;
}
int ans=ask(i,note,2,1);
ar[i]=ans;
}
cout<<"!"<<' ';
for(int i=1;i<=n;i++){
cout<<ar[i]<<' ';
}
cout<<endl;
}
int main(){
int t;cin>>t;
cout.flush(); //此处也可以为 cin.ignore();
while(t--){
solve();
cout.flush();
}
}
---------------------------------------------------------------------------------------------------
第一次写博客,也不知道链接可不可以用,不能用也无所谓了。