A题:
水题,只要全部元素设置为1就行了。
代码:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#include<stack>
using namespace std;
typedef long long ll;
const int MAXN=2e5+5;
const int mod=1e9+7;
int main()
{
int t;
cin>>t;
while(t--)
{
int n;
cin>>n;
for(int i=1;i<=n;i++)
{
cout<<1<<" ";
}
cout<<endl;
}
}
B题:
假设a<=b,我们可以发现,当b是a的倍数时,lcm(a,b)会取得最小值,即b=ka。则a+ka=n,(k+1)a=n, k越小,a和b越接近,则b越小,lcm(a,b)也越小。则我们就是要去找n的最小因子(除了1),除掉便是a。
代码:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#include<stack>
using namespace std;
typedef long long ll;
const int MAXN=2e5+5;
const int mod=1e9+7;
ll gcd(ll a, ll b)
{
if (b == 0)
return a;
else if (a < b)
return gcd(b, a);
else
return gcd(b, a % b);
}
ll lcm(ll a, ll b)
{
return a / gcd(a, b) * b;
}
int main()
{
int t;
cin>>t;
while(t--)
{
int n;
cin>>n;
if(n==2)
{
cout<<1<<" "<<1<<endl;
continue;
}
if(n==3)
{
cout<<1<<" "<<2<<endl;
continue;
}
int a1,b1;
int f=-1;
for(int i=2;i<=sqrt(n);i++)
{
if(n%i==0)
{
f=1;
a1=n/i;
b1=n-a1;
break;
}
}
if(f==1) cout<<min(a1,b1)<<" "<<max(a1,b1)<<endl;
else cout<<1<<" "<<n-1<<endl;
}
}
C题:
当数组中全部a[i]=i的时候,答案肯定为0,当只有一段连续区间(l=<i<=r)a[i]!=i时,直接一次操作将区间的数变为a[i]=i,答案为1。当有两段或两段以上的连续区间不满足要求时,我们可以记录下第一段的开头位置L,和最后一段的结尾位置R,使用一次操作,先将最后一段不满足要求的区间变为a[i]=i,从最后一段区间的开头-1位置一直到第一段的开头都可以先变为不满足要求的,之后再使用一次操作,将这段区间变为合法的,那么只需两次便可完成,答案为2。
代码:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#include<stack>
#include<vector>
using namespace std;
#define iis std::ios::sync_with_stdio(false); cin.tie(0)
typedef long long ll;
const int MAXN=2e5+5;
const int inf=0x3f3f3f3f;
int a[MAXN];
int main()
{
int t;
cin>>t;
while(t--)
{
int n;
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i];
}
int ans=0;
int f=0;
for(int i=1;i<=n;i++)
{
if(a[i]!=i)
{
if(f==0)
{
f=1;
ans++;
}
}
else f=0;
}
if(ans==0) cout<<0<<endl;
else if(ans==1) cout<<1<<endl;
else cout<<2<<endl;
}
}
D题:
比赛时没写出来,看完大佬的思路,大概是这样,我们假设第i个数字需要保留到最后,那么只看左边,则第i-1的数字必须删掉,一直往左推,到1的时候往左是n,直到只剩下一个数。当i为奇数时,那么可以发现,i前面的偶数位置都会删掉,奇数位置都会保留,i后面奇数位置都会删掉,偶数位置都会保留,反之当i为偶数时,i前面奇数位置都会删掉,i后面偶数位置都会删掉。
比如 1 2 3 4 5 6 7。
当我们选择4保留的时候,那么3删掉—>1 6 5 6 7, 删掉 1---->5 6 13 ,删掉6---->18。
当我们选择5保留的时候,那么4删掉—>1 2 8 6 7, 删掉 2---->6 7 9 ,删掉7---->15。
所以我们枚举要保留的位置,利用前缀和求得答案。
代码:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#include<stack>
using namespace std;
typedef long long ll;
const int MAXN=2e5+5;
const int mod=1e9+7;
ll s[MAXN];
ll a[4][MAXN];
int main()
{
int n;
cin>>n;
a[1][0]=0;
a[2][0]=0;
for(int i=1;i<=n;i++)
{
cin>>s[i];
a[1][i]=a[1][i-1];
a[2][i]=a[2][i-1];
if(i&1) a[1][i]+=s[i];
else a[2][i]+=s[i];
}
ll ans=0;
for(int i=1;i<=n;i++)
{
if(i&1)
{
ans=max(a[1][i]+a[2][n]-a[2][i],ans);
}
else
{
ans=max(ans,a[2][i]+a[1][n]-a[1][i]);
}
}
cout<<ans<<endl;
}