昨天打了一下edu103的比賽,場內做出了A,B,C,C一開始沒開long long ,卡了半個小時,D沒時間了,今天補了一下,發現D就是一個簡單dp。
題目鏈接:https://codeforces.com/contest/1476
A. K-divisible Sum
思路:本題就是一個鴿巢定理,推一個公式就行。場內居然wa了3發,做了25分鐘。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int _;
ll n, k;
void solve(){
cin >> _;
while(_--){
cin >> n >> k;
if(max(1ll, k/n)*n <= k){
cout << k/n + ((k%n==0)?0:1) << "\n";
}
else{
cout << 1ll + ((n%k==0)?0:1) << "\n";
}
}
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
solve();
return 0;
}
B. Inflation
思路:求一個前綴和,當概率條件不滿足的時候,才需要更新ans。是一個貪心策略,從前往後遍歷一下,即可。要注意,增加ans的時候要上取整。我擔心失精度,沒用double,都用的整數。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int _;
int n, k;
ll a[110];
ll sum[110];
void solve(){
cin >> _;
while(_--){
cin >> n >> k;
for(int i = 1; i <= n; i++){
cin >> a[i];
}
sum[0] = 0;
for(int i = 1; i <= n; i++){
sum[i] = sum[i-1] + a[i];
}
ll ans = 0;
for(int i = 2; i <= n; i++){
if(100*a[i] > k*(sum[i-1]+ans)){
ll now = (100*a[i] - k*(sum[i-1]+ans))/k;
if(100*a[i] > k*(sum[i-1] + ans + now)){
now++;
}
ans += now;
}
}
cout << ans << "\n";
}
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
solve();
return 0;
}
C. Longest Simple Cycle
思路:求最長的簡單環。如果一個鏈的向後連接點相同,從這裏往後要重新計數。枚舉到一個 c i c_i ci要更新以這裏爲封閉環的情況。碰到必須更新的時候,要注意重新開始。同時,要注意一處細節,如下圖。(開始被卡住是因爲沒開longlong)
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int _;
int n;
int c[100010];
int a[100010];
int b[100010];
int fen[100010];
void solve(){
cin >> _;
while(_--){
cin >> n;
for(int i = 1; i <= n; i++){
cin >> c[i];
}
for(int i = 0; i < n; i++){
cin >> a[i];
}
for(int i = 0; i < n; i++){
cin >> b[i];
}
for(int i = 0; i <= n; i++){
fen[i] = 0;
}
for(int i = 1; i <= n; i++){
if(a[i] == b[i]){
fen[i] = 1;
}
}
a[n] = b[n] = 0;
fen[n] = 1;
fen[1] = 0;
ll ans = 0;
ll now = 0;
for(int i = 1; i <= n; i++){
if(fen[i]){
now += (1ll*c[i] - 1);
ans = max(now, ans);
if(i == n){
now = 0;
}
else{
now = 2*1ll;}
}
else{
if(i == 1){
now += abs(1ll*a[i] - 1ll*b[i]);
}
else{
now += (1ll*c[i] - 1);
ans = max(ans, now);
now -= (1ll*c[i] - 1);
now += abs(min(1ll*a[i], 1ll*b[i]) - 1) + abs(max(1ll*a[i], 1ll*b[i]) - 1ll*c[i]);
now = max(now, abs(1ll*b[i] - 1ll*a[i]));
}
now += 2;
}
}
cout << ans << "\n";
}
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
solve();
return 0;
}
D. Journey
思路:求從一點開始向右RLRLR,,,的最長距離,向左開始LRLR,,,和自身城市之和就是答案。我們考慮兩個dp,一個維護從一點向右的情況,一個維護從一點向左的情況。因爲每一次更新dp,都要變向,所以方向信息需要記錄,我們把方向狀態開到dp數組裏就行了。
#include <bits/stdc++.h>
using namespace std;
int _;
int n;
string s;
int lft[300010][2];
int rht[300010][2];
void solve(){
cin >> n;
cin >> s;
s = "0" + s;
for(int i = 0; i <= n; i++){
if(i == 0){
lft[i][0] = lft[i][1] = 0;
}
else{
if(s[i] == 'L'){
lft[i][0] = lft[i-1][1] + 1;
lft[i][1] = 0;
}
else{
lft[i][1] = lft[i-1][0] + 1;
lft[i][0] = 0;
}
}
}
for(int i = n; i >= 0; i--){
if(i == n){
rht[i][0] = rht[i][1] = 0;
}
else{
if(s[i+1] == 'R'){
rht[i][1] = rht[i+1][0] + 1;
rht[i][0] = 0;
}
else{
rht[i][0] = rht[i+1][1] + 1;
rht[i][1] = 0;
}
}
}
for(int i = 0; i <= n; i++){
cout << lft[i][0] + rht[i][1] + 1 << " ";
}
cout << "\n";
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin >> _;
while(_--){
solve(); }
return 0;
}