Codeforces Round #728 (Div. 2)【ABC】

A.Pretty Permutations

构造,处理奇数前三个顺序1,2,3->3,1,2
然后搞,反思一下自己把最后一个搬在第一个FastFastWA
着急了代码比较丑但是能看懂凑合看

/*
 * @Descripttion: 
 * @Author: ssw
 * @Date: 2021-05-30 04:49:52
 * @LastEditors: ssw
 * @LastEditTime: 2021-06-25 23:45:35
 */
#include<iostream>
using namespace std;
int n, m;
int main(){
    cin >> n;
    while(n--)
    {
        cin >> m;
        if(m==2)
        {
            cout << 2 << ' ' << 1 << endl;
            continue;
        }
        else if (m==3)
        {
            cout << 3 << ' ' << 1 << ' ' << 2 << endl;
            continue;
        }
        else if(m%2==0)
        {
            for (int i = 1; i <= m;i+=2)
            {
                cout << i + 1 << ' ' << i << ' ';
            }
            cout << endl;
            continue;
        }
        else
        {
            cout << 3 << ' ' << 1 << ' ' << 2 << ' ';
            for (int i = 4; i <= m;i+=2)
            {
                cout << i + 1 << ' ' << i << ' ';
            }
            cout << endl;
            continue;
        }
        
        
    }
    return 0;
}

B.Pleasant Pairs

找见符合的 ( i , j ) (i,j) (i,j)使得 a i ∗ a j = = i + j & i < j \quad a_i*a_j==i+j \quad\& \quad i<j aiaj==i+j&i<j
化简一下式子根据已经有的 i i i跳着找 j j j速度会快一丢丢
a j = i + j a i j = k ∗ a i − i k ∈ Z + \begin{aligned} &a_j=\frac{i+j}{a_i}\\ &j=k*a_i-i\quad k \in Z^+\\ \end{aligned} aj=aii+jj=kaiikZ+
详细的找的话k第一个取值大概看下就是:
i < j k ∗ a i − i = j > i k ∗ a i > 2 ∗ i k > 2 ∗ i a i k ∈ Z + k = ⌈ 2 ∗ i a i ⌉ j = ⌈ 2 ∗ i a i ⌉ ∗ a i − i \begin{aligned} &i<j\\ &k*a_i-i=j>i\\ &k*a_i>2*i\\ &k>\frac{2*i}{a_i}\quad k \in Z^+\\ &k=\lceil \frac{2*i}{a_i}\rceil\\ j=\lceil \frac{2*i}{a_i}\rceil *a_i-i \end{aligned} j=ai2iaiii<jkaii=j>ikai>2ik>ai2ikZ+k=ai2i
之后每次自增a[i]查找直到满足条件
**加粗样式**
不嫌丢人,我vector写挂了???(反思*2

/*
 * @Descripttion: 
 * @Author: ssw
 * @Date: 2021-05-30 04:49:52
 * @LastEditors: ssw
 * @LastEditTime: 2021-06-26 00:49:37
 */
#include<iostream>
#include<vector>
#include<cmath>
#include<algorithm>
using namespace std;
using ll = long long;
int n, m;
int main(){
    cin >> n;
    while(n--)
    {
        cin >> m;
        ll data[100005];
        ll sum=0;
        for (int i = 1; i <= m;++i)
        {
            cin >> data[i];
        }
        for (int i = 1; i < m;i++)
        {
            ll k = ceil(2.0 * i / data[i]);
            // cout << i << ' '<<k<<endl;
            for (ll j = k * data[i] - i; j <= m; j += data[i])
            {
                if(j+i==data[i]*data[j]&&j>i)
                    sum++;
                
            }
        }
        cout << sum << endl;
    }
    return 0;
}

C. Great Graphs

题目挺巧妙,闲了继续写

6.26更新:


总结:给出dist数组,有负边但是不存在那种越搞越小的,暗示临近点之间负边有对应正边

想法:刚做的时候就把dist数组当成前缀和数组去做了后来发现问题很大,理解起来就是图中的边要自己构造给出了距离数组,可以先默认是个点集合然后把点的顺序做个变化,排序之后就变成一个递增数组,图像就变成了下面这样:

a
b
d
1
2
3
4

其中a,b,c均大于零,因为先将dist数组排序了
其实还能这样在进一步理解我说的临近边有负边:

a
-a
b
-b
d
-d
1
2
3
4

之后计算的时候就要忽略临近边的计算了,因为条件临近边的值已经相互抵消了
那么答案就来到了:把这些边加起来边负号就是能拥有的最大负边数
直接算跨过两个边的:1->3,2->4,跨过三个边的:1->4
计算还是要加起来

a
b
d
e
d3-d1
d5-d3
1
2
3
4
5

可见是可以相互化简得,所以这个问题复杂度就是排序复杂度
还有一点就是注意longlong和输入数据量大小
不然就不会像我一样wa完又T了

/*
 * @Descripttion: 
 * @Author: ssw
 * @Date: 2021-05-30 04:49:52
 * @LastEditors: ssw
 * @LastEditTime: 2021-06-26 14:32:44
 */
#include<iostream>
#include<vector>
#include<cmath>
#include<cstdio>
#include<algorithm>
using namespace std;
using ll = long long;
int n, m;
bool cmp(ll a, ll b){
    return a < b;
}
int main(){
    cin >> n;
    while(n--)
    {
        cin >> m;
        ll data[100005];
        ll sum=0;
        for (int i = 1; i <= m;++i)
        {
            scanf("%lld", &data[i]);
        }
        sort(data + 1, data + m + 1, cmp);
        // for (int i = 1; i <= m; ++i)
        // {
        //     cout << data[i] << endl;
        // }
        if(m<=2)
        {
            cout << 0 << endl;
            continue;
        }

        for (int i = 2; i < m;++i)
        {
            if(m*1.0/i>2)
            {
                for (int j = 1; j <= i; ++j)
                {
                    sum += (data[m - j + 1] - data[j]);
                }
            }
            else
            {
                for (int j = 1; j <= m - i; ++j)
                {
                    sum += (data[m - j + 1] - data[j]);
                }
            }
            // for (int j = 1; j <= m - i; ++j)
            // {
            //     ll num = (data[j + i] - data[j]);
            //     if(num>0)
            //         sum -= num;
            //     else
            //         sum += num;
            //     // cout << sum << endl;
            // }
        }
        // cout << -sum << endl;
        printf("%lld\n", -sum);
        // if (sum > 0)
        //     cout << -sum * 2 << endl;
        // else
        //     cout << sum * 2 << endl;
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

数学小牛马

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值