成外联赛题解
前言,第一次正规的写题解,不喜勿喷
T1 舞蹈机器⼈(dance)
题目
题意
在⼀个拥有⽆限⼤⼩的⼆维平⾯的原点处,有⼀个舞蹈机器⼈,这个机器⼈将在这个平⾯上跳舞。
这个机器⼈每次可以向⾃⼰的前⽅移动⼀个单位的⻓度,由于它需要在移动的过程中跳舞,因此,舞蹈机器⼈每移动⼀次,就必须向左或右⽅向旋转 ,即如果此次机器⼈往或下⽅向进⾏了⼀次移动,那么,下⼀次就只能往左或右⽅向进⾏⼀次移动。最开始时,它可以选择上下左右四个⽅向中的任意⼀个作为初始⽅向。现在,机器⼈根据上述规则⼀共移动了s步,请问,机器⼈最终可以到达多少个不同的终点?机器⼈到达终点时的⽅向可以忽略。
输入与输出
输入
597
输出
179400
思路
首先想到暴力(也就是DFS),通过暴力,制作一个二维的bool数组,第k步设为1,其余为0。
然后遍历这个数组,ans记录可能位置。
但很明显,这个方法它超时了。我们要采取更优化的方法,这能数学求解。
对于机器⼈的移动⽽⾔,因为第⼆次移动的⽅向必须是在第⼀次的基础上进⾏旋转,所以对于整个机器⼈的移动过程⽽⾔,每两次移动就相当于是在正⽅形的对⻆线上移动了⼀次(即斜着⾛了⼀步),也就是每两步一个周期。
因此奇(qi)数步的思路为(1+(n+1)/2)*(n+1)
偶数则为(n/2+1)*(n/2+1)
时间复杂度仅为O(1).
代码
#include<bits/stdc++.h>
using namespace std;
int main() {
// freopen("dance.in","r",stdin);考试不加会G掉的
// freopen("dance.out","r",stdout);
long long n;//十年OI一场空,不开_______见祖宗
cin>>n;
if(n%2==1) cout<<(1+(n+1)/2)*(n+1)<<'\n';//如思路
else cout<<(n/2+1)*(n/2+1)<<'\n';
}
T2 划分(partition)
题目

思路
· 30pts
暴⼒搜索划分⽅案即可
· 60pts 使用一个动态规划维护
· 80pts 发现手玩一定是n/2
. 100pts思路
注意到⼀个关键性质gcd(a+b,c)>=gcd(a,b,c)。
证明是容易的,设d=gcd(a,b,c) ,那么d|(a+b) ,于是gcd(a+b,c)>=gcd(a,b,c)肯定成⽴。
这个性质说明最优划分⼀定只会划分为两段,否则将相邻的两段合并起来⼀定更优。
于是滚⼀个前缀和,暴⼒枚举分割点即可
代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e18;
int t,n;
vector<int> s(n + 1);
int main() {
cin>>t;
while (t--) {
cin>>n;
for (int i=1;i<=n;i++) {
cin>>s[i];
s[i]+=s[i-1];
}
int ans=0;
for(int i=1;i<=n;i++) {
ans=max(ans,gcd(a[i],a[n]-a[i]));
}
cout<<ans<<'\n'
}
}

浙公网安备 33010602011771号