Codeforces 2025/6/7 日志

C. You Soared Afar With Grace

题目大意:给你一个2行n列的二维数组,问你能否通过交换两列元素的方法,对于每个 i=1,2,…,ni=1,2,…,n , ai=bn+1−i,如果能写出其具体操作步骤,不能就输出-1

#1 每次必须交换1列元素,所以对于两列元素,必须有{ai,bi},{bi,ai}

#2 n为奇数时,中间可以插一个

思路:首先记录ai = bi 和 有ai,bi但无bi,ai的数量,大于1就不能构造出,为1就可以把他换到中间,且只有一个时,n时一定时奇数的

代码:

void solve()

{

    int n;

    cin >> n;

    vector<PII> v(n+1);

    map<PII,int> mp;

    for (int i = 1; i <= n; i ++ ) cin >> v[i].x;

    for (int i = 1; i <= n; i ++ ) cin >> v[i].y;

    for (int i = 1; i <= n; i ++ ) mp[{v[i].x,v[i].y}] = i;

    int cnt = 0,pos = 1;

    for (int i = 1; i <= n; i ++ )

        if (v[i].x == v[i].y || !mp.count({v[i].y,v[i].x}))

            cnt ++ , pos = i;

    if (cnt > 1)

    {

        cout<<-1<<endl;

        return ;

    }

    vector<PII> ans;

    function<void(int,int)> sp = [&](int x,int y) -> void

    {

        ans.emplace_back(x,y);

        mp[v[x]] = y, mp[v[y]] = x;

        swap(v[x],v[y]);

    };

    if (cnt == 1 && pos != (n+1)/2) sp(pos,(n+1)/2);

    for (int i = 1; i <= n / 2; i ++ )

    {

        int p = mp[{v[i].y,v[i].x}];

        if (p != n - i + 1)

            sp(p,n - i + 1);

    }

    cout<<ans.size()<<endl;

    for (auto it = ans.begin(); it != ans.end(); it ++ )

        cout<<it->x<<" "<<it->y<<endl;

}

链接:Problem - C - Codeforces

C. Saraga

题目大意:给定两个字符串,让你构造出一个字符串,使至少有两种方法将该字符串分为非空的两串,这两串分属于第一个字符串的前缀,和第二个字符串的后缀

#1 第一串的首字母和第二串的尾字母是不动的

思路:贪心靠右记录字符串2中每个字符出现的位置,除1串首字符和2串尾字符外,只要有1个公共字符即满足条件,我们构造出的字符串即为1串到该字符和2串中该字符到末尾,最后从左到右遍历一遍即可

代码:

void solve()

{

    string s1,s2; cin >> s1 >> s2;

    map<char,int> mp;

    int n1 = s1.size(), n2 = s2.size();

    s1 = ' ' + s1, s2 = ' ' + s2;

    for (int i = 1; i < n2; i ++ )

        mp[s2[i]] = i;

    int ans = 1e9;

    string s = "";

    for (int i = 2; i <= n1; i ++ )

        if (mp.count(s1[i]))

        {

            if (ans > i + n2 - mp[s1[i]])

            {

                ans = i + n2 - mp[s1[i]];

                s = s1.substr(1,i) + s2.substr(mp[s1[i]]+1);

            }

            ans = min(ans,i + n2 - mp[s1[i]] );

        }

    if (ans == 1e9) s = "-1";

    cout<<s<<endl;

}

链接:Problem - C - Codeforces

D. Satyam and Counting

题目大意:给你一堆坐标,让你计算这一堆中有多少个由不同的三个点组成的直角三角形

#1 纵坐标是0和1

#2 思考怎么构造出直角三角形

思路:第一种情况,有(x,0)和(x,1)两点,则该两点可以和除这两点外的所有点组成直角三角形,第二种情况,有(x,0)点时另有(x-1,1),(x+1,1)两点则可组成,(x,1)情况则与之对应

代码:

void solve()

{

    int n; cin >> n;

    vector<array<int,2>> v(n+1);

    vector<PII> d(n);

    map<int,int> mp1, mp2;

    for (int i = 0; i < n; i ++ )

    {

        cin >> d[i].x >> d[i].y;

        v[d[i].x][d[i].y] ++ ;

        if (d[i].y == 0) mp1[d[i].x] ++ ;

        if (d[i].y == 1) mp2[d[i].x] ++ ;

    }

    i64 ans = 0;

    for (int i = 0; i <= n; i ++ )

    {

        if (v[i][0] + v[i][1] == 2) ans += n - 2;

    }

    for (int i = 0; i < n; i ++ )

    {

        if (d[i].y == 0)

        {

            if (mp2.count(d[i].x-1) && mp2.count(d[i].x+1)) ans ++ ;

        }

        else

        {

            if (mp1.count(d[i].x-1) && mp1.count(d[i].x+1)) ans ++ ;

        }

    }

    cout<<ans<<endl;

}

链接:Problem - D - Codeforces

F. Sakurako's Box

题目大意:给你数组a1,a2...an,让你求a1*a2+a1*a3+...+a(n-1)*an/(n*(n-1)/2)mod(1e9+7)的值

#1 费马小定理求逆元

#2 考虑推公式

思路:该公式可推为

注意爆int即可

代码:

i64 qmi(i64 a,int b,int p)
{
    i64 res = 1 % p;
    while (b)
    {
        if (b & 1) res = res * a % p;
        a = a * a % p;
        b >>= 1;
    }
    return res;
}

void solve()
{
    int n;
    cin >> n;
    vector<i64> v(n+1),pre(n+1);
    for (int i = 1; i <= n; i ++ ) cin >> v[i];
    for (int i = 1; i <= n; i ++ )
        pre[i] = pre[i-1] + v[i];

    i64 res = 0;
    for (int i = 1; i <= n - 1; i ++ )
    {
        res = (v[i]*((pre[n] - pre[i])%M)+res)%M;
    }
    cout<<res * qmi((i64)n*(n-1)/2%M,M-2,M)%M<<endl;
}

链接:Problem - F - Codeforces

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值