#51050: C++ 陣列單幹 3ms


haoting (顥庭)

學校 : 不指定學校
編號 : 196309
來源 : [61.58.96.80]
最後登入時間 :
2025-10-06 03:04:03

這題可以用循環陣列的概念想,用一個head陣列紀錄「頭」index,每次轉動 head[i] 加上正負相反的步數(記得取模)。

由於C++負數取模會是負的(相當於正的取模多個負號),取完一次模後記得+n在取一次(第一次取模保證範圍縮為-n+1~n-1,第二次則變為0~n-1)

因為字母範圍只有1~26,可以用陣列存,再用跑的找max,一回合時間複雜度O(26n)。

用multiset有點煩,反正範圍不大陣列單幹也行。當然也可以用priority_queue找。

#include<iostream>
using namespace std;

int main()
{
    int m,n,k;
    cin>>m>>n>>k;
    char s[m][n];      
    int head[m] = {};   //紀錄頭,初始值為0

    for(int i = 0;i<m;i++){
        for(int j = 0;j<n;j++){
            cin>>s[i][j];
        }
    }

    int sum = 0;
    for(int ki = 0;ki<k;ki++)
    {
        //頭轉動
        for(int i = 0;i<m;i++){
            int arr;
            cin>>arr;
            //正的為向右轉->頭位置移動相反;負同理
            //第一個取模->範圍縮到-n+1~n-1,+n後再取模->範圍縮到0~n-1
            head[i] = ((head[i]-arr)%n+n)%n;
        }
        //算分數
        for(int i = 0;i<n;i++){
            //直接轉ASCII,用陣列紀錄出現次數
            int temp[int('z'-'a')+1] = {};

            //head[i2]為第i2個字串的頭index,加完n一樣要取模
            for(int i2 = 0;i2<m;i2++)
                temp[int(s[i2][(head[i2]+i)%n] - 'a')]++;
           
            //算出現最多次的字
            int ma = 0;
            for(int i3 = 0;i3<int('z'-'a')+1;i3++)
                ma = max(ma,temp[i3]);
            sum+=ma;
        }
    }
    cout<<sum<<'\n';
   
    return 0;
}