题目链接https://codeforces.com/contest/1712/problem/B
题目大意-给一个序列1-n,再来求一个序列p,保证 lcd(pi,i)最大,其实只要从最后往前面遍历,步长为2,交换相邻两元素就行啦,但是这里我当时sb啦,加了一个条件,求出
lcd(pi,i+1)+lcd(p(i+1),i) 还有 lcd(pi,i)+lcd(p(i+1),i+1) ,如果前者大,就交换pi.这里因为是用的int来存。其中pi的数据范围为1-100000。自然而然的100000与99999这样的数据,求lcd就爆int啦
错误代码:
#include <bits/stdc++.h>
//#include <iostream>
using namespace std;
//#define push() push_back()
//#define endl '\n'
//#define ull unsigned long long
//#define int long long
//const int N=5e3;
//int a[N+10][N+10];
#define rep(i, a, b) for (int i = a; i < b; i++)
#define rrep(i,a,b) for (int i = a; i > b; i--)
int gcd(int m,int n){
int r;
while( (r=m%n)!=0 ){ m=n; n=r; }
return n;
}
int lcd(int n,int m){
return n*m/gcd(n,m);
}
int f[100005];
void solve(){
int n;
int t1,t2;
cin>>n;
rep(i,0,n+3) f[i]=i;
for(int i=n;i>=2;i-=2){
t1=(lcd(i,f[i-1])+lcd(i-1,f[i]));
t2=(lcd(i-1,f[i-1])+lcd(i,f[i]));
if(t1>t2){
swap(f[i],f[i-1]);
}
}
rep(i,1,n+1) cout<<f[i]<<" ";
cout<<endl;
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
// ofstream cout("Eout.txt");
int t;
cin>>t;
while(t--)
solve();
return 0;
}
正确代码(但非最简单):
#include <bits/stdc++.h>
//#include <iostream>
using namespace std;
//#define push() push_back()
//#define endl '\n'
//#define ull unsigned long long
#define int long long
//const int N=5e3;
//int a[N+10][N+10];
#define rep(i, a, b) for (int i = a; i < b; i++)
#define rrep(i,a,b) for (int i = a; i > b; i--)
int gcd(int m,int n){
int r;
while( (r=m%n)!=0 ){ m=n; n=r; }
return n;
}
int lcd(int n,int m){
return n*m/gcd(n,m);
}
int f[100005];
void solve(){
int n;
int t1,t2;
cin>>n;
rep(i,0,n+3) f[i]=i;
for(int i=n;i>=2;i-=2){
t1=(lcd(i,f[i-1])+lcd(i-1,f[i]));
t2=(lcd(i-1,f[i-1])+lcd(i,f[i]));
if(t1>t2){
swap(f[i],f[i-1]);
}
}
rep(i,1,n+1) cout<<f[i]<<" ";
cout<<endl;
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
// ofstream cout("Eout.txt");
int t;
cin>>t;
while(t--)
solve();
return 0;
}
总结:
求最小公倍数考虑一下int会不会爆