AtCoder Beginner Contest 375

A - Seats

思路

枚举即可

AC代码

    #include<bits/stdc++.h>
    #define endl '\n'
    #define int int long long
    #define pb push_back
    #define bs bitset
    using namespace std;
    typedef pair<char,int> PCI;
    typedef pair<int,int> PII;
    typedef priority_queue<int> PQ;

    const int N = 2e5+10, MAX = 1e9, INF = -1e9;

    int n;
    string s;
    int ans=0;

    signed main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0);
        cin>>n;
        cin>>s;
        s=" "+s;
        for(int i=1;i<=n-2;i++){
            if(s[i]=='#'&&s[i+1]=='.'&&s[i+2]=='#')ans++;
        }
        cout<<ans<<endl;

        return 0;
    }

B - Traveling Takahashi Problem

思路

按照题意模拟即可,注意从开始从原点出发,最后还要回到原点

AC代码

    #include<bits/stdc++.h>
    #define endl '\n'
    #define int int long long
    #define pb push_back
    #define bs bitset
    using namespace std;
    typedef pair<char,int> PCI;
    typedef pair<int,int> PII;
    typedef priority_queue<int> PQ;

    const int N = 2e5+10, MAX = 1e9, INF = -1e9;

    int n;
    double x[N];
    double y[N];
    double ans=0;

    signed main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0);
        cin>>n;
        x[0]=0.0;y[0]=0.0;y[n+1]=0.0;x[n+1]=0.0;
        for(int i=1;i<=n;i++){
            cin>>x[i]>>y[i];
        }
        for(int i=0;i<=n;i++){
            ans+=sqrt((x[i]-x[i+1])*(x[i]-x[i+1])+(y[i]-y[i+1])*(y[i]-y[i+1]));
        }
        printf("%.12lf",ans);


        return 0;
    }

C - Spiral Rotation

思路

读题费了我很长时间,最后10min啃样例才顿悟开始做题,debug最后超赛时8minAC了,遗憾至极,其实C的题目就是提示,(我没有做题看题目的习惯,以后还是要看看), 我们来看看这个过程,整个过程可以看成两个步骤:首先将 \((x, y)\) 变换成 \((N+1-x, y)\) ,这一步就是把原先的点按照 \(x\) 的中轴对称过去,然后第二步将 \((N+1-x, y)\) 变换成 \((y, N + 1 - x)\) ,就是交换 \(x\)\(y\) ,在数学上就是按照从左上到右下的对角线对称过去(参考中学反函数图像的形成);
如下图,\(A\) 点先按照水平绿线对称到 \(A'\) 点,再按照斜的对称线对称到 \(A''\) 点,整体就是按照中心 \(O\) 顺时针旋转了90度:


再读题意结合样例不难发现,最外层只参与一次旋转,向内第二次层会转两次,以此类推,所以设由外向内层数为 \(key\) ,则第 \(key\) 层最终就旋转了 \(key\) \(mod4\) 次,考虑类似于冒泡排序的交换方式,编写旋转函数即可;

AC代码

    #include<bits/stdc++.h>
    #define endl '\n'
    #define int int long long
    #define pb push_back
    #define bs bitset
    using namespace std;
    typedef pair<char,int> PCI;
    typedef pair<int,int> PII;
    typedef priority_queue<int> PQ;

    const int N = 3005, MAX = 1e9, INF = -1e9;

    int n;
    char g[N][N];

    void f(int key,int m){
        int a=m;int b=n+1-m;
        while(key--){
            for(int i=a;i<b;i++){
                char c=g[a][i];
                swap(c,g[i][b]);
                swap(c,g[b][a+b-i]);
                swap(c,g[a+b-i][a]);
                swap(c,g[a][i]);
            }
        }
    
    }

    signed main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0);
        cin>>n;
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                cin>>g[i][j];
            }
        }
        for(int i=1;i<=n/2;i++){
            f(i%4,i);
        }
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                cout<<g[i][j];
            }
            cout<<endl;
        }
        


        return 0;
    }

D - ABA

思路

要达成长度为3的回文串,就需要左右两边相同的字符夹中间任意字符,用map储存每种字符的索引数组,结合样例不难发现对于每个索引,答案就是其后的索引与其作差减一再求和,即:$$\sum_{i=1}^{l-1 }\sum_{j=i+1}^la[j]-a[i]-1$$,时间复杂度为 \(O(n^2)\) ( \(l\) 是每个字符索引数组长度) ,简化公式,用前缀和简化得:$$\sum_{i=0}^l s[l-1]-s[i]-(l-1-i)(a[i]+1)$$,至此我们就在线性时间解决这个问题了;

AC代码

    #include<bits/stdc++.h>
    #define endl '\n'
    #define int int long long
    #define pb push_back
    #define bs bitset
    using namespace std;
    typedef pair<char,int> PCI;
    typedef pair<int,int> PII;
    typedef priority_queue<int> PQ;

    const int N = 2e5+10, MAX = 1e9, INF = -1e9;

    string s;
    map<char ,vector<int>> mp;
    int ans=0;

    signed main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0);
        cin>>s;s=" "+s;
        int n=s.size();
        for(int i=1;i<=n;i++){
            mp[s[i]].pb(i);
        }
        for(auto i:mp){
            int l=i.second.size();
            int res=0;
            int s[l];
            for(int j=0;j<l;j++){
            res+=i.second[j];
            s[j]=res;
            }
            for(int j=0;j<l;j++){
                ans+=(s[l-1]-s[j]-(l-1-j)*(i.second[j]+1));
            }
        }
        cout<<ans<<endl;
        
    }

E - 3 Team Division

思路

\(N\)数量级较小,时间限制有4秒,应该想出一个多项式级别时间复杂度的算法,考虑动态规划:设 \(dp[i][j][k]\) 储存的是前 \(i\) 个成员安排好后,第一组强度为 \(j\) ,第二组强度为 \(k\) 的最小操作数,由于 \(j\) , \(k\)
已知,故第三组的强度也已知,为方便,用pre数组预处理出前 \(i\) 个的强度和,转移方程如下:

\[dp[i][j][k]=\begin{cases} min(dp[i][j][k],dp[i-1][j-b[i]][k]+bool), & b[i]<=j, \\ \\ min(dp[i][j][k],dp[i-1][j][k-b[i]]+bool), & b[i]<=k,\\ \\ min(dp[i][j][k],dp[i-1][j][k]+bool), & b[i]<=pre[i]-j-k. \end{cases} \]

\(bool\) 为转移操作是否实行,时间复杂度为三次方,足够解决这个问题了;(注意特判,如果强度和不是3的倍数,那就一定不可能;还可以用滚动数组压缩空间);

AC代码

    #include<bits/stdc++.h>
    #define endl '\n'
    #define int int long long
    #define pb push_back
    #define bs bitset
    using namespace std;
    typedef pair<char,int> PCI;
    typedef pair<int,int> PII;
    typedef priority_queue<int> PQ;

    const int N = 1e2 + 5, M = 5e2 + 5;
    const int inf = 0x3f3f3f3f3f3f3f3f;

    int n;
    int a[N], b[N], dp[N][M][M];
    void solve()
    {
        cin >> n;
        int sum = 0;
        for (int i = 1; i <= n; i++)
        {
            cin >> a[i] >> b[i];
            sum += b[i];
        }
        if (sum % 3 != 0)
        {
            cout << -1 << endl;
            return;
        }
        memset(dp, inf, sizeof dp);
        dp[0][0][0] = 0, sum /= 3;
        for (int i = 0; i < n; i++)
        {
            for (int j = 0; j <= sum; j++)
            {
                for (int k = 0; k <= sum; k++)
                {
                    if (dp[i][j][k] == inf)
                        continue;
                    if (j + b[i + 1] <= sum)
                        dp[i + 1][j + b[i + 1]][k] = min(dp[i + 1][j + b[i + 1]][k], dp[i][j][k] + (a[i + 1] != 1));
                    if (k + b[i + 1] <= sum)
                        dp[i + 1][j][k + b[i + 1]] = min(dp[i + 1][j][k + b[i + 1]], dp[i][j][k] + (a[i + 1] != 2));
                    dp[i + 1][j][k] = min(dp[i + 1][j][k], dp[i][j][k] + (a[i + 1] != 3));
                }
            }
        }
        if (dp[n][sum][sum] == inf)
        {
            cout << -1 << endl;
        }
        else
            cout << dp[n][sum][sum] << endl;
    }

    signed main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0);
        solve();

        return 0;
    }

t.b.c.

posted @ 2024-10-13 13:23  Oaths  阅读(51)  评论(0)    收藏  举报