CF - Playing in a Casino

题意:相当于比大小的赌博计算赌徒一共需要支出多少赌资

比大小的规则很简单,是

在这个游戏中,有一个套牌由n卡。每张卡都有m数字写在上面。每个n玩家从一副牌中只收到一张牌。

然后所有玩家成对玩,每对玩家只玩一次。因此,例如,如果总共有四个玩家,则进行六场比赛:第一场比赛对第二场比赛,第一场比赛对第三场比赛,第一场比赛对第四场比赛,第二场比赛对第三场比赛,第二场比赛对第四场比赛,第三场比赛对第四场比赛。

 解:

一开始其实放纵自己用了一个铁会时间超限的方法,一分钟写出来了,但是智能过样例,第三个test就卡住了,就是输入时就进行相减了

错误示范:

#include<bits/stdc++.h>
using namespace std;
int t,n,m,u,ans;
int main()
{
    cin>>t;
    while(t--)
    {
        cin>>n>>m;
        vector<int> a[30];
        ans=0;
        //输入第一行
        for(int j=0; j<m; j++)
        {
            cin>>u;
            a[0].push_back(u);
        }
        //后续
        for(int i=1; i<n; i++)
        {
            for(int j=0; j<m; j++)
            {
                cin>>u;
                a[i].push_back(u);
                for(int k=0; k<i; k++)
                {
                    ans+=abs(a[k][j]-a[i][j]);
                }
            }
        }
        cout<<ans<<endl;

    }
    return 0;
}

由于绝对值这个东西不确定,我们很讨厌,所以我们可以通过排序接触正负号的不确定性,使得我们算出的值符号被我们绝对掌握!

注意,由于列向相减和横向相减可不是一样的东西

 所以我们要进行行列置换,我们可以通过一个二维数组在输入时就可以达到该目的

(注意这里输入完可以进行一个特判,如果只有一行数据那么没有进行博弈的其他对象,赌资将会是0,n=1时,可以直接输出0然后continue进行下一次判断

回到前面,如果n>1,接下来要对每列进行排序

 

 排序之后我们可以发现规律:

拿这一列排序后为 1,2,3,4,5举例

由于顺序已经拍好了,1-2的绝对值等同于2-1,所以1-后面的值的绝对值等同于(2+3+4+5)-4*1

同理,2-后面的值等同于(3+4+5)-3*2

后面同理,且这样子我们可以保证是正数。

(设i从0开始)

那么通过找规律,可以发现改列最后的赌资就是a【i】*i - a【i】*(n-i-1)即a【i】*(2i-n+1)

把每一列的赌资算出来之后都加到ans中最终就能得出答案。

这道题错了很多次,主要原因一个是比较少使用vector,一个是没养成注意精度范围的习惯

首先,vector的定义可以直接带入变量开辟空间

vector<vector<int>>v(n,vector<int>(m))

因为题目说n和m在1到3e5之间且n*m小于3e5

3e5是不大的,但是如果之间vector<vector<int>>v(3e5,vector<int>(3e5)),那么开辟的空间大小就是9e10,爆掉了,所以要用输入的n和m来开辟空间。

(注意由于进行了行列转换,这里的一维要用m,二维用n)

其次,当定义vector时指定了大小,那么它就相当于这个大小的数组了,赋值时直接使用a【i】【j】=xxx就行,不可以a.push_back(xxx),因为push_back是在原来的基础上再开辟空间添加数据,而我们已经开辟好了空间,原本的基础上就是m*n的大小了(这就是为什么输入时直接cin>>a[j][i]而不用push_back)

最后,注意精度范围,数值大小在1到1e6之间,大范围数值涉及到乘法时就需要注意int还够不够充裕了,这里的ans涉及了,这里的i指的是1~n,n最大3e5,a【i】【j】最大1e6,一相乘就变成了3e11,所以必须用long long int,而vector中的数值也需要用long long int,对范围做判断即可,不做再多解释了。

所以这道题:

#include<bits/stdc++.h>
using namespace std;
int t,n,m,u;
long long int ans;
int main()
{
    cin>>t;
    while(t--)
    {
        cin>>n>>m;
        vector<vector<long long int>> a(m,vector<long long int>(n));
        ans=0;
        //输入
        for(int i=0; i<n; i++)
        {
            for(int j=0; j<m; j++)
            {
                cin>>a[j][i];
            }
        }
        //特判
        if(n==1){
            cout<<"0"<<endl;
            continue;
        }
        for(int j=0;j<m;j++){
            sort(a[j].begin(),a[j].end());
            for(int i=0;i<n;i++){
                ans+=a[j][i]*(2*i+1-n);
            }
        }
        cout<<ans<<endl;
    }
    return 0;
}

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值