G - Magical Cookies 解説
by
orthogonal
別解
実数\(a_1, \ldots, a_n\)がすべて同じである必要十分条件は
\[ n\sum_{i=1}^n a_i^2=\left( \sum_{i=1}^n a_i\right)^2. \]
これはコーシー=シュワルツの不等式で証明できます。
この事実を用いると、各英小文字をそれぞれのASCIIコードに置き換え、各行・各列の要素の和と二乗和を管理すれば、evimaの解法と同じ\(O((H+W)^2)\)の時間で解けます。
C++コード (44ms, 3840KB)
#include <iostream>
#include <vector>
using namespace std;
#define ll long long
ll square(ll x){
return x*x;
}
int main() {
ios_base::sync_with_stdio(false);
cin.tie(0);
//以上為輸入輸出流速度優化
int H, W;
cin >> H >> W;
vector<pair<ll, ll>> row_sum(H, {0, 0});
vector<pair<ll, ll>> column_sum(W, {0, 0});
for(int i=0;i<H;i++){
string s;
cin >> s;
for(int j=0;j<W;j++){
int ind=s[j]-'a';
row_sum[i].first+=ind;
row_sum[i].second+=ind*ind;
column_sum[j].first+=ind;
column_sum[j].second+=ind*ind;
}
}
pair<ll, ll> row_sum_delta={0, 0};
pair<ll, ll> column_sum_delta={0, 0};
while(true){
vector<int> index_rowToDelete;
vector<int> index_columnToDelete;
ll column_sum_delta1=0;
ll column_sum_delta2=0;
if(W>1){
for(int i=0;i<H;i++){
if((row_sum[i].second-row_sum_delta.second)*W==square(row_sum[i].first-row_sum_delta.first)){
index_rowToDelete.push_back(i);
int ind=(row_sum[i].first-row_sum_delta.first)/W;
column_sum_delta1+=ind;
column_sum_delta2+=square(ind);
}
}
}
if(H>1){
for(int i=0;i<W;i++){
if((column_sum[i].second-column_sum_delta.second)*H==square(column_sum[i].first-column_sum_delta.first)){
index_columnToDelete.push_back(i);
int ind=(column_sum[i].first-column_sum_delta.first)/H;
row_sum_delta.first+=ind;
row_sum_delta.second+=square(ind);
}
}
}
if(index_rowToDelete.empty() && index_columnToDelete.empty()){
cout << H*W;
return 0;
}
//改H, W, row_sum, column_sum
column_sum_delta.first+=column_sum_delta1;
column_sum_delta.second+=column_sum_delta2;
vector<pair<ll, ll>> new_row_sum;
vector<pair<ll, ll>> new_column_sum;
for(int i=0, ind=0;i<H; i++){
if(ind<index_rowToDelete.size() && i==index_rowToDelete[ind]){
ind++;
}
else{
new_row_sum.push_back(row_sum[i]);
}
}
for(int j=0, ind=0;j<W;j++){
if(ind<index_columnToDelete.size() && j==index_columnToDelete[ind]){
ind++;
}
else{
new_column_sum.push_back(column_sum[j]);
}
}
row_sum=new_row_sum;
column_sum=new_column_sum;
H=row_sum.size();
W=column_sum.size();
}
return 0;
}
投稿日時:
最終更新:
