問題集
https://onlinejudge.u-aizu.ac.jp/beta/room.html#WUPC2020/info
解説
https://drive.google.com/drive/folders/16n_1q3evzq2sUJtAdjBT7OnxNW-UpQx4
その他
解いておきたい
// 座標圧縮 // 変換テーブルを返す VI make_compress_table(vector<ll>& A){ // 変換表 auto B = A; sort(ALL(B)); auto it = unique(ALL(B)); B.erase(it, B.end()); return B; } ll compress_by_table(VI& T, ll v){ return lower_bound(ALL(T), v) - T.begin(); }
// 座標圧縮 // Aをそのまま書き換えるver void compress(VI& A){ ll N = A.size(); auto B = A; sort(ALL(B)); auto it = unique(ALL(B)); B.erase(it, B.end()); rep(i,N){ A[i] = lower_bound(ALL(B), A[i]) - B.begin(); } }
struct AccSum{ vector<ll> Ac; ll L; AccSum(){} AccSum(vector<ll> &A){ L = A.size(); Ac.resize(L+1); FOR(i, 0, L){ Ac[i+1] = Ac[i] + A[i]; } } // sum of [a, b] ll sum(ll a, ll b){ if(a<0) return -1; if(b>L-1) return -1; return Ac[b+1] - Ac[a]; } }; // できること // 一点追加 // 範囲和 // ei1333's BIT struct BIT { VI data; BIT(ll sz) { data.assign(++sz, 0); } ll sum(ll k) { ll ret = 0; for(++k; k > 0; k -= k & -k) ret += data[k]; return (ret); } // [i, j] ll range_sum(ll i, ll j){ if(i==0){ return sum(j); }else{ return sum(j) - sum(i-1); } } void add(ll k, ll x) { for(++k; k < SZ(data); k += k & -k) data[k] += x; } }; // 座標圧縮 // 変換テーブルを返す VI make_compress_table(vector<ll>& A){ // 変換表 auto B = A; sort(ALL(B)); auto it = unique(ALL(B)); B.erase(it, B.end()); debug(B); return B; } ll compress_by_table(VI& T, ll v){ return lower_bound(ALL(T), v) - T.begin(); } int main(){ cin.tie(0); ios::sync_with_stdio(false); // input ll N,T; cin>>N>>T; VI A(N); rep(i, N) cin >> A[i]; AccSum Acc(A); BIT bit(410000); // compress VI V; rep(i,N){ ll v = Acc.sum(0, i); V.push_back(v); V.push_back(v+T); } auto tbl = make_compress_table(V); // 累積和をBITに登録 rep(i,N){ ll v = Acc.sum(0,i); ll idx = compress_by_table(tbl, v); bit.add(idx, 1); } ll ans=0; rep(l, N){ ll v = T; if(l!=0){ v += Acc.sum(0,l-1); } ll limit = compress_by_table(tbl, v); if(limit>0){ ans += bit.sum(limit-1); } ll idx = compress_by_table(tbl, Acc.sum(0,l)); bit.add(idx, -1); // 登録から消す } p(ans); return 0; }
int main(){ // input ll n,l,k;cin>>n>>l>>k; k--; string s;cin>>s; // character count VI C(26); for(char c : s){ ll v = c-'a'; C[v]++; } VS S(n); // n本の文字列 ll t = 0; // same prefix index // phase 1 ll idx=0; while(S[k].size()<l){ if(C[idx]==0){ idx++; continue; } ll Cp = C[idx]; char c = 'a'+idx; if(Cp>k-t){ // enough FOR(i,t,k+1) S[i] += c; C[idx] -= k-t+1; } else{ FOR(i,t,t+Cp) S[i] += c; t += Cp; C[idx] = 0; } } // phase 2 idx=0; rep(i,n){ if(S[i].size()==l) continue; while(S[i].size()<l){ while(C[idx]==0)idx++; char c = 'a'+idx; S[i] += c; C[idx]--; if(C[idx]==0)idx++; } } sort(ALL(S)); for(string s : S){ p(s); } return 0; }
bool is_A_line(string& s){ for(char c : s){ if(c!='A') return false; } return true; } // for codeforces void solve(){ // input ll R,C;cin>>R>>C; VS S(R); rep(i,R)cin>>S[i]; // impossible easy case { ll p_cnt=0; for(string s : S){ for(char c : s){ if(c=='P') p_cnt++; } } if(p_cnt==R*C){ p("MORTAL"); return; } ll a_cnt = R*C - p_cnt; if(a_cnt==R*C){ p(0); return; // 忘れがち } } // P-exist range ll min_x = inf; ll min_y = inf; ll max_x = -1; ll max_y = -1; rep(i,R){ rep(j,C){ char c = S[i][j]; if(c=='P'){ chmin(min_y,i); chmax(max_y,i); chmin(min_x,j); chmax(max_x,j); } } } // about x rep(i,R){ string s = S[i]; ll len = max_x - min_x + 1; string sub = s.substr(min_x, len); if(min_y<=i && i<=max_y) continue; // 間だとダメ if(is_A_line(sub)){ p(1); return; } } // about y rep(x,C){ stringstream ss; rep(i,R) ss<<S[i][x]; string s = ss.str(); ll len = max_y - min_y + 1; string sub = s.substr(min_y, len); if(min_x<=x && x<=max_x) continue; // 間だとダメ if(is_A_line(sub)){ p(1); return; } } // 一撃で終わらなかった場合のコーナー { string s = S[0]; if(s[0]=='A' or s.back()=='A'){ p(2); return; } s = S[R-1]; if(s[0]=='A' or s.back()=='A'){ p(2); return; } } // 以降、コーナーは全てP // P-exist rangeをつつみこむAラインがあれば2回で済む // about x rep(i,R){ string s = S[i]; ll len = max_x - min_x + 1; string sub = s.substr(min_x, len); if(is_A_line(sub)){ p(2); return; } } // about y rep(x,C){ stringstream ss; rep(i,R) ss<<S[i][x]; string s = ss.str(); ll len = max_y - min_y + 1; string sub = s.substr(min_y, len); if(is_A_line(sub)){ p(2); return; } } // はじっこにAがあるなら3回で可能 if(S[0].find("A")!=string::npos){ p(3); return; } if(S[R-1].find("A")!=string::npos){ p(3); return; } rep(i,R){ if(S[i][0]=='A'){ p(3);return; } if(S[i][C-1]=='A'){ p(3);return; } } p(4); } int main(){ cin.tie(0); ios::sync_with_stdio(false); // input ll N; cin>>N; while(N--)solve(); return 0; }
// 借り物 // https://ei1333.github.io/luzhiled/snippets/math/euler-phi.html int64_t euler_phi(int64_t n) { int64_t ret = n; for(int64_t i = 2; i * i <= n; i++) { if(n % i == 0) { ret -= ret / i; while(n % i == 0) n /= i; } } if(n > 1) ret -= ret / n; return ret; } // 1 to n までのnと互いに素である個数 ll eulers_totient_function(ll n){ ll n_original = n; // 10^10まで可能 VI P; for(ll i=2; i*i<=n; i++){ if(n%i==0){ P.push_back(i); } while(n%i==0) n/=i; } P.push_back(n); // 素因数を使って実際に求める n = n_original; for(ll p : P){ if(p==1) continue; // 盲点 n -= n/p; } return n; } void solve(){ ll a,m;cin>>a>>m; ll g = gcd(a,m); ll n = m/g; ll ans = eulers_totient_function(n); // ll ans = euler_phi(n); p(ans); } int main(){ cin.tie(0); ios::sync_with_stdio(false); // input ll N; cin>>N; while(N--)solve(); return 0; }