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 ...
标程太长,告辞。