T1
题解
首先可以发现ab之间都要线性无关才是最优的,不难发现我们实际要求矩阵的秩
在线性代数中,一个矩阵A的列秩是A的线性独立的纵列的极大数目。类似地,行秩是A的线性无关的横行的极大数目。通俗一点说,如果把矩阵看成一个个行向量或者列向量,秩就是这些行向量或者列向量的秩,也就是极大无关组中所含向量的个数。
然后有一个定理
矩阵的秩实际上是行秩和列秩的最小值,怎么求线性无关呢?高斯消元然后最后有几个不全是0的,如果一个可以被另一个消掉,那肯定是线性相关啦
代码:
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
const double eps=1e-8;
const int N=205;
double a[N][N],b[N][N];
int gauss(int n,int m)
{
for (int i=1,x=1;i<=n && x<=m;i++,x++)
{
int num=i;
for (int j=i;j<=n;j++)
if (fabs(a[num][x])<fabs(a[j][x])) num=j;
if (fabs(a[num][x])<eps) {i--;continue;}
if (num!=i) for (int j=x;j<=m;j++) swap(a[num][j],a[i][j]);
for (int j=i+1;j<=n;j++)
{
double t=a[j][x]/a[i][x];
for (int k=x;k<=m;k++) a[j][k]-=a[i][k]*t;
}
}
int ans=0;
for (int i=1;i<=n;i++)
{
bool sb=0;
for (int j=1;j<=m;j++) if (fabs(a[i][j])>eps) {sb=1;break;}
if (sb) ans++;
}
return ans;
}
int main()
{
freopen("kangaroo.in","r",stdin);
freopen("kangaroo.out","w",stdout);
int n,m;scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++) scanf("%lf",&a[i][j]),b[i][j]=a[i][j];
int ans=gauss(n,m);
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++) a[j][i]=b[i][j];
ans=min(ans,gauss(m,n));
printf("%d",ans);
}
T2
题解:
大概是要一个菊花图的样子
建立2k个点,Ti 令 2i-1 和 2i 当根。
(2i−1,2j)(2i,2j−1)(j<i)
(
2
i
−
1
,
2
j
)
(
2
i
,
2
j
−
1
)
(
j
<
i
)
(2i−1,2j−1)(2i,2j)(j>i)
(
2
i
−
1
,
2
j
−
1
)
(
2
i
,
2
j
)
(
j
>
i
)
代码:
T3
题解:
f[i] 切 1..i 最后一个数最小的最后一刀的位置,正着处理
然后倒着处理g[i] 切 i..n 最后一个数最小,字典序最大的第一刀位置
注意到由于是数字比较,所以位数多的一定大(没有前导 0 的话)
比较数字大小可以用后缀数组
代码:
挖坑待填