2018SD省队集训R1 D4

18 篇文章 0 订阅
16 篇文章 0 订阅

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 当根。
(2i1,2j)(2i,2j1)(j<i) ( 2 i − 1 , 2 j ) ( 2 i , 2 j − 1 ) ( j < i )
(2i1,2j1)(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 的话)
比较数字大小可以用后缀数组

代码:

挖坑待填

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值