Codeforces Round #696 (Div. 2) 部分簡要題解
阿新 • • 發佈:2021-02-03
技術標籤:# Codeforces
A. Puzzle From the Future
貪心,每位儘可能取1,如果不能取1,就取0。
#include<bits/stdc++.h> #define pb push_back #define fi first #define se second #define sz(x) (int)x.size() #define cl(x) x.clear() #define all(x) x.begin() , x.end() #define rep(i , x , n) for(int i = x ; i <= n ; i ++) #define per(i , n , x) for(int i = n ; i >= x ; i --) #define mem0(x) memset(x , 0 , sizeof(x)) #define mem_1(x) memset(x , -1 , sizeof(x)) #define mem_inf(x) memset(x , 0x3f , sizeof(x)) #define debug(x) cerr << #x << " = " << x << '\n' #define ddebug(x , y) cerr << #x << " = " << x << " " << #y << " = " << y << '\n' #define ios std::ios::sync_with_stdio(false) , cin.tie(0) using namespace std ; typedef long long ll ; typedef long double ld ; typedef pair<int , int> pii ; typedef pair<ll , ll> pll ; typedef double db ; const int mod = 998244353 ; const int maxn = 2e5 + 10 ; const int inf = 0x3f3f3f3f ; const double eps = 1e-6 ; int main() { ios ; int T ; cin >> T ; while(T --) { int n ; cin >> n ; string s ; cin >> s ; vector<int> a(n + 1) , b(n + 1) ; for(int i = 1 ; i <= n ; i ++) a[i] = (s[i - 1] - '0') ; b[1] = 1 ; for(int i = 2 ; i <= n ; i ++) { int lst = a[i - 1] + b[i - 1] ; for(int j = 1 ; j >= 0 ; j --) { if(a[i] + j != lst) { b[i] = j ; break ; } } } for(int i = 1 ; i <= n ; i ++) cout << b[i] ; cout << '\n' ; } return 0 ; }
B. Different Divisors
,其中是質數。列舉即可。注意素數篩的範圍略大一些,就夠用了。
#include<bits/stdc++.h> #define pb push_back #define fi first #define se second #define sz(x) (int)x.size() #define cl(x) x.clear() #define all(x) x.begin() , x.end() #define rep(i , x , n) for(int i = x ; i <= n ; i ++) #define per(i , n , x) for(int i = n ; i >= x ; i --) #define mem0(x) memset(x , 0 , sizeof(x)) #define mem_1(x) memset(x , -1 , sizeof(x)) #define mem_inf(x) memset(x , 0x3f , sizeof(x)) #define debug(x) cerr << #x << " = " << x << '\n' #define ddebug(x , y) cerr << #x << " = " << x << " " << #y << " = " << y << '\n' #define ios std::ios::sync_with_stdio(false) , cin.tie(0) using namespace std ; typedef long long ll ; typedef long double ld ; typedef pair<int , int> pii ; typedef pair<ll , ll> pll ; typedef double db ; const int mod = 998244353 ; const int maxn = 2e5 + 10 ; const int inf = 0x3f3f3f3f ; const double eps = 1e-6 ; int ans[maxn] ; struct Easymath { ll qpow(ll a , ll b) //快速冪 { if(b < 0) return 0 ; ll ans = 1 ; a %= mod ; while(b) { if(b & 1) ans = (ans * a) % mod ; b >>= 1 , a = (a * a) % mod ; } return ans % mod ; } ll ksc_log(ll x , ll y , ll mod) //快速乘 { x %= mod , y %= mod ; ll ans = 0; while(y) { if(y & 1) ans = (ans + x) % mod ; y >>= 1 ; x = (x + x) % mod ; } return ans; } ll ksc_O1(ll x , ll y , ll mod) //快速乘 { x %= mod , y %= mod ; ll z = (ld)x * y / mod ; ll ans = x * y - z * mod ; if(ans < 0) ans += mod ; else if(ans >= mod) ans -= mod ; return ans ; } int cnt = 0 ; bool vis[maxn] ; int prime[maxn] ; void get_prime(int up) //素數篩 { memset(vis , 0 , sizeof(vis)) ; vis[1] = 1 ; for(int i = 2 ; i <= up ; i ++) { if(!vis[i]) prime[++ cnt] = i ; for(int j = 1 ; j <= cnt && i * prime[j] <= up ; j ++) { vis[i * prime[j]] = 1 ; if(i % prime[j] == 0) break ; } } mem_inf(ans) ; for(int i = 1 ; i <= cnt ; i ++) for(int j = i + 1 ; j <= cnt ; j ++) { int mn = min(prime[i] - 1 , prime[j] - prime[i]) ; ans[mn] = min(ans[mn] , prime[i] * prime[j]) ; } for(int i = 20000 ; i >= 1 ; i --) ans[i] = min(ans[i + 1] , ans[i]) ; } //begin 判定大素數 ll mul(ll a , ll b , ll mod) { ll ret = 0 ; while(b) { if(b & 1) ret = (ret + a) % mod ; a = (a + a) % mod ; b >>= 1 ; } return ret ; } ll pow(ll a , ll b , ll mod) { ll ret = 1 ; while(b) { if(b & 1) ret = mul(ret , a , mod) ; a = mul(a , a , mod) ; b >>= 1 ; } return ret ; } bool check(ll a , ll n) { ll x = n - 1 ; int t = 0 ; while((x & 1) == 0) { x >>= 1 ; t ++ ; } x = pow(a , x , n) ; ll y ; rep(i , 1 , t) { y = mul(x , x , n) ; if(y == 1 && x != 1 && x != n - 1) return 1 ; x = y ; } if(y != 1) return 1 ; return 0 ; } bool Miller_Rabin(ll n) { if(n == 2) return 1 ; if(n == 1 || !(n & 1)) return 0 ; const int arr[12] = {2,3,5,7,11,13,17,19,23,29,31,37} ; rep(i , 0 , 11) { if(arr[i] >= n) break ; if(check(arr[i] , n)) return 0 ; } return 1 ; } //end 判定大素數 ll get_inv(ll x) //逆元 { return qpow(x , mod - 2) % mod ; } ll inv1[maxn] ; //乘法逆元 void init1(int up) { inv1[1] = 1 ; for(int i = 2 ; i <= up ; i ++) inv1[i] = (ll)(mod - mod / i) * inv1[int(mod % (ll)i)] % mod ; } ll fac[maxn] ; ll inv[maxn] ; //階乘逆元 void init(int up) { fac[0] = fac[1] = inv[0] = inv[1] = 1 ; for(int i = 2 ; i <= up ; i ++) { fac[i] = fac[i - 1] * i % mod ; inv[i] = -inv[mod % i] * (mod / i) % mod ; while(inv[i] < 0) inv[i] += mod ; } for(int i = 2 ; i <= up ; i ++) inv[i] = inv[i] * inv[i - 1] % mod ; } ll C(int n , int m) { return fac[n] * inv[m] % mod * inv[n - m] % mod ; } } em ; int main() { ios ; int T ; em.get_prime(40005) ; cin >> T ; while(T --) { int d ; cin >> d ; cout << ans[d] << '\n' ; } return 0 ; }
C. Array Destruction
在第一次操作時,序列的最大數一定是其中一個運算元,列舉另一個運算元即可。在後續操作中,每次操作的兩個運算元都是固定的。複雜度。
#include<bits/stdc++.h> #define pb push_back #define fi first #define se second #define sz(x) (int)x.size() #define cl(x) x.clear() #define all(x) x.begin() , x.end() #define rep(i , x , n) for(int i = x ; i <= n ; i ++) #define per(i , n , x) for(int i = n ; i >= x ; i --) #define mem0(x) memset(x , 0 , sizeof(x)) #define mem_1(x) memset(x , -1 , sizeof(x)) #define mem_inf(x) memset(x , 0x3f , sizeof(x)) #define debug(x) cerr << #x << " = " << x << '\n' #define ddebug(x , y) cerr << #x << " = " << x << " " << #y << " = " << y << '\n' #define ios std::ios::sync_with_stdio(false) , cin.tie(0) using namespace std ; typedef long long ll ; typedef long double ld ; typedef pair<int , int> pii ; typedef pair<ll , ll> pll ; typedef double db ; const int mod = 998244353 ; const int maxn = 1e6 + 10 ; const int inf = 0x3f3f3f3f ; const double eps = 1e-6 ; int cnt[maxn] ; int main() { ios ; int T ; cin >> T ; while(T --) { int n ; cin >> n ; n *= 2 ; vector<int> a(n) ; for(int i = 0 ; i < n ; i ++) cin >> a[i] ; sort(all(a)) ; for(int i = 0 ; i < n - 1 ; i ++) { bool flag = true ; int now = a[i] + a[n - 1] ; for(int j = 0 ; j < n ; j ++) cnt[a[j]] ++ ; if(cnt[a[i]] > 0) cnt[a[i]] -- ; if(cnt[a[n - 1]] > 0) cnt[a[n - 1]] -- ; now = a[n - 1] ; for(int j = n - 2 ; j >= 0 ; j --) { if(cnt[a[j]] == 0) continue ; cnt[a[j]] -- ; if(cnt[now - a[j]] == 0) flag = false ; if(cnt[now - a[j]] > 0) cnt[now - a[j]] -- ; now = a[j] ; } if(flag) { cout << "YES\n" ; for(int j = 0 ; j < n ; j ++) cnt[a[j]] = 0 ; int now = a[i] + a[n - 1] ; cout << now << '\n' ; for(int j = 0 ; j < n ; j ++) cnt[a[j]] ++ ; if(cnt[a[i]] > 0) cnt[a[i]] -- ; if(cnt[a[n - 1]]) cnt[a[n - 1]] -- ; cout << a[i] << ' ' << a[n - 1] << '\n' ; now = a[n - 1] ; for(int j = n - 2 ; j >= 0 ; j --) { if(cnt[a[j]] == 0) continue ; cnt[a[j]] -- ; if(cnt[now - a[j]] == 0) flag = false ; if(cnt[now - a[j]] > 0) cnt[now - a[j]] -- ; cout << a[j] << ' ' << now - a[j] << '\n' ; now = a[j] ; } goto ff ; } for(int j = 0 ; j < n ; j ++) cnt[a[j]] = 0 ; } cout << "NO\n" ; ff : ; for(int i = 0 ; i < n ; i ++) cnt[a[i]] = 0 ; } return 0 ; }
D. Cleaning
套路題。
首先容易發現在對操作後會變成。
在對操作後會變成。
然後發現如果,最多會影響。
所以預處理字首和字尾,列舉即可。
#include<bits/stdc++.h>
#define pb push_back
#define fi first
#define se second
#define sz(x) (int)x.size()
#define cl(x) x.clear()
#define all(x) x.begin() , x.end()
#define rep(i , x , n) for(int i = x ; i <= n ; i ++)
#define per(i , n , x) for(int i = n ; i >= x ; i --)
#define mem0(x) memset(x , 0 , sizeof(x))
#define mem_1(x) memset(x , -1 , sizeof(x))
#define mem_inf(x) memset(x , 0x3f , sizeof(x))
#define debug(x) cerr << #x << " = " << x << '\n'
#define ddebug(x , y) cerr << #x << " = " << x << " " << #y << " = " << y << '\n'
#define ios std::ios::sync_with_stdio(false) , cin.tie(0)
using namespace std ;
typedef long long ll ;
typedef long double ld ;
typedef pair<int , int> pii ;
typedef pair<ll , ll> pll ;
typedef double db ;
const int mod = 998244353 ;
const int maxn = 1e6 + 10 ;
int main()
{
ios ;
int T ;
cin >> T ;
while(T --)
{
int n ;
cin >> n ;
vector<int> a(n) ;
vector<int> pre(n) ;
vector<int> suf(n) ;
vector<int> pre_cnt(n , 0) ;
vector<int> suf_cnt(n , 0) ;
for(int i = 0 ; i < n ; i ++) cin >> a[i] ;
function<void()> init = [&]()
{
pre[0] = a[0] ;
pre_cnt[0] = 0 ;
for(int i = 1 ; i < n ; i ++)
{
int mn1 = pre[i - 1] ;
int mn2 = a[i] ;
int mn = min(mn1 , mn2) ;
mn1 -= mn ;
mn2 -= mn ;
pre[i] = mn2 ;
pre_cnt[i] = pre_cnt[i - 1] + (mn1 != 0) ;
}
suf[n - 1] = a[n - 1] ;
suf_cnt[n - 1] = 0 ;
for(int i = n - 2 ; i >= 0 ; i --)
{
int mn1 = suf[i + 1] ;
int mn2 = a[i] ;
int mn = min(mn1 , mn2) ;
mn1 -= mn ;
mn2 -= mn ;
suf[i] = mn2 ;
suf_cnt[i] = suf_cnt[i + 1] + (mn1 != 0) ;
}
//for(int i = 0 ; i < n ; i ++) cout << suf[i] << " \n"[i == n - 1] ;
//for(int i = 0 ; i < n ; i ++) cout << suf_cnt[i] << " \n"[i == n - 1] ;
} ;
init() ;
function<bool()> ok = [&]()
{
vector<int> b(n) ;
for(int i = 0 ; i < n ; i ++) b[i] = a[i] ;
for(int i = 0 ; i < n - 1 ; i ++)
{
int mn = min(b[i] , b[i + 1]) ;
b[i] -= mn ;
b[i + 1] -= mn ;
}
for(int i = 0 ; i < n ; i ++) if(b[i] != 0) return false ;
return true ;
} ;
function<bool(int)> ok2 = [&](int t)
{
int lst = 0 ;
if(t - 1 >= 0) lst += pre[t - 1] ;
if(t - 1 >= 0 && pre_cnt[t - 1] >= 1) return false ;
int nxt = 0 ;
if(t + 2 < n) nxt += suf[t + 2] ;
if(t + 2 < n && suf_cnt[t + 2] >= 1) return false ;
int now1 = a[t] ;
int now2 = a[t + 1] ;
swap(now1 , now2) ;
//cout << lst << ' ' << now1 << ' ' << now2 << ' ' << nxt << '\n' ;
int mn1 = min(lst , now1) ;
lst -= mn1 ;
now1 -= mn1 ;
int mn3 = min(now1 , now2) ;
now1 -= mn3 ;
now2 -= mn3 ;
int mn2 = min(nxt , now2) ;
nxt -= mn2 ;
now2 -= mn2 ;
//cout << lst << ' ' << now1 << ' ' << now2 << ' ' << nxt << '\n' ;
return lst == 0 && now1 == 0 && nxt == 0 && now2 == 0 ;
} ;
//cout << ok2(0) << '\n' ;
bool flag = ok() ;
for(int i = 0 ; i < n - 1 ; i ++) flag |= ok2(i) ;
if(flag) cout << "YES\n" ;
else cout << "NO\n" ;
}
return 0 ;
}
E. What Is It?
逆向思考,把恆等排列變成某個排列,需要花費最大代價是多少。操作次數是,每次選擇一個,然後和或交換,選擇較遠的那個交換。
寫程式碼時要對的奇偶性分類討論。
#include<bits/stdc++.h>
using namespace std ;
int main()
{
std::ios::sync_with_stdio(false) , cin.tie(0) ;
int T ;
cin >> T ;
while(T --)
{
int n ;
cin >> n ;
vector<int> p(n + 1) ;
for(int i = 1 ; i <= n ; i ++) p[i] = i ;
vector<pair<int , int>> t ;
long long ans = 0 ;
if(n % 2 == 1)
{
swap(p[1] , p[n]) ;
t.push_back({1 , n}) , ans += 1ll * (n - 1) * (n - 1) ;
for(int i = 2 ; i <= n / 2 ; i ++)
{
swap(p[i] , p[n]) ;
t.push_back({i , n}) , ans += 1ll * (n - i) * (n - i) ;
swap(p[n + 1 - i] , p[1]) ;
t.push_back({n + 1 - i , 1}) , ans += 1ll * (n - i) * (n - i) ;
}
swap(p[(n + 1) / 2] , p[1]) ;
t.push_back({(n + 1) / 2 , 1}) , ans += 1ll * ((n + 1) / 2 - 1) * ((n + 1) / 2 - 1) ;
}
else
{
swap(p[1] , p[n]) ;
t.push_back({1 , n}) , ans += 1ll * (n - 1) * (n - 1) ;
for(int i = 2 ; i <= n / 2 ; i ++)
{
swap(p[i] , p[n]) ;
t.push_back({i , n}) , ans += 1ll * (n - i) * (n - i) ;
swap(p[n + 1 - i] , p[1]) ;
t.push_back({n + 1 - i , 1}) , ans += 1ll * (n - i) * (n - i) ;
}
}
cout << ans << '\n' ;
for(int i = 1 ; i <= n ; i ++) cout << p[i] << " \n"[i == n] ;
cout << t.size() << '\n' ;
reverse(t.begin() , t.end()) ;
for(auto u : t) cout << u.first << ' ' << u.second << '\n' ;
}
return 0 ;
}
F. 1 2 3 4 ...
標程太長,告辭。