Codeforces Round #847 (Div. 3)
A. Polycarp and the Day of Pi
先纯一下圆周率前30位,然后暴力就好了
#include <bits/stdc++.h>
using std::cin;
using std::cout;
using std::string;
int read(){...}
const string tmp = "314159265358979323846264338327";
void solve(){
string s; cin >> s;
int res = 0;
for( int i = 0 ; i < std::min( s.size() , tmp.size() ) ; i ++ ){
if( s[i] == tmp[i] ) res ++;
else break;
}
printf("%d\n" , res );
}
int32_t main(){
for( int t = read() ; t ; t -- )
solve();
return 0;
}
B. Taisia and Dice
令s-r为第一个数,保证序列不上升,且和为s。dfs枚举一下就行。
#include <bits/stdc++.h>
using std::cin;
using std::cout;
using std::string;
const int N = 55;
int a[N] , n , s , r ;
bool flag ;
int read(){...}
void dfs( int i , int sum ){
if( flag ) return;
if( i == n + 1 ){
if( sum != 0 ) return ;
flag = true;
for( int j = 1 ; j <= n ; j ++ ) printf("%d%c" , a[j] , " \n"[j==n] );
return;
}
for( int j = std::min( a[i-1] , sum ) ; j >= 1 ; j -- )
a[i] = j , dfs( i+1 , sum - j );
return ;
}
void solve(){
n = read() , s = read() , r = read() , flag = false;
memset( a , 0 , sizeof a ) , a[1] = s - r;
dfs( 2 , r );
return ;
}
int32_t main(){
for( int t = read() ; t ; t -- )
solve();
return 0;
}
C. Premutation
每个位置的数一定出现了n-1次,而没有出现该数的序列就是这个数缺失的序列,这个序列后面的数向前错一位保证对其
#include <bits/stdc++.h>
using namespace std;
int read(){
int x = 0 , f = 1 , ch = getchar();
while( (ch < '0' || ch > '9') && ch != '-' ) ch = getchar();
if( ch == '-' ) f = -1 , ch = getchar();
while( ch >= '0' && ch <= '9' ) x = ( x << 3 ) + ( x << 1 ) + ch - '0' , ch = getchar();
return x * f;
}
void solve(){
int n = read();
vector< vector<int> > a( n , vector<int>(n-1) );
for( auto & it : a )
for( auto &i : it ) i = read();
vector<int> vis(n);
for( int i = 0 ; i < n ; i ++ ){
map<int,int> st;
for( int j = 0 ; j < n ; j ++ ){
if( vis[j] ) st[ a[j][i-1] ] ++;
else st[ a[j][i] ] ++;
}
for( auto [ k , v] : st ){
if( v == 1 ){
for( int j = 0 ; j < n ; j ++ )
if( vis[j] == 0 && a[j][i] == k ) vis[j] = 1;
}
else printf("%d " , k );
}
}
printf("\n");
return;
}
int32_t main(){
for( int t = read() ; t ; t -- )
solve();
return 0;
}
但是看了jiangly发现有更简单的做法,当找到出第一个数,第一数确实的序列是[2,n]
的完整序列
#include <bits/stdc++.h>
using namespace std;
int read() {...}
void solve() {
int n = read() , t;
vector<vector<int> > a(n, vector<int>(n - 1));
for (auto &it: a)
for (auto &i: it) i = read();
map<int, int> st;
for (auto it: a) st[it[0]]++;
for (auto [k, v]: st) if (v == n - 1) t = k;
for (auto it: a) {
if (it[0] == t) continue;
printf("%d ", t);
for (auto i: it) printf("%d ", i);
printf("\n");
return;
}
return;
}
int32_t main() {
for (int t = read(); t; t--)
solve();
return 0;
}
D. Matryoshkas
数字很少,直接暴力就好。
#include <bits/stdc++.h>
using namespace std;
int read(){...}
void solve(){
int n = read() , res = 0 , t;
map<int,int> st;
for( int i = 1 , x ; i <= n ; i ++ ) x = read() , st[x]++;
while( !st.empty() ){
vector<int> erase;
res ++ , t = -1;
for( auto &[k,v] : st ){
if( k == t+1 || t == -1 ) t = k , v --;
else break;
if( v == 0 ) erase.push_back(k);
}
for( auto it : erase ) st.erase(it);
}
printf("%d\n" , res );
}
int32_t main(){
for( int t = read() ; t ; t -- )
solve();
return 0;
}
E. Vlad and a Pair of Numbers
我这里是先用lowbit把原来的数拆开,然后这些数保证了异或为x,然后因为\(x=\frac{a+b}{2}\),所以\(a+b-x=x\),也就是说还有x保证和是a+b,这部分因为异或是0所以要平均分,即\(\frac{x}{2}\)并且些数lowbit拆开后不能与x拆开的数重复。
#include <bits/stdc++.h>
using namespace std;
#define int long long
int read(){
int x = 0 , f = 1 , ch = getchar();
while( (ch < '0' || ch > '9') && ch != '-' ) ch = getchar();
if( ch == '-' ) f = -1 , ch = getchar();
while( ch >= '0' && ch <= '9' ) x = ( x << 3 ) + ( x << 1 ) + ch - '0' , ch = getchar();
return x * f;
}
#define lowbit(x) ( x &-x )
void solve(){
int x = read();
if( x & 1 ) {
printf("-1\n");
return ;
}
set<int> a , b ;
for( int t = x , p ; t > 0 ; ) p = lowbit(t) , a.insert(p) , t -= p;
for( int t = (x >> 1) , p ; t > 0 ; ) p = lowbit(t) , b.insert(p) , t -= p;
for( auto i : b ){
if( a.count(i) ) {
printf("-1\n");
return ;
}
}
int A = 0 , B = 0;
for( auto i : a ) A += i ;
for( auto i : b ) A += i , B += i ;
cout << A << " " << B << "\n";
}
int32_t main(){
for( int t = read() ; t ; t -- )
solve();
return 0;
}
赛后发现有\(O(1)\)的做法,观察我构造的值,\(a=\frac{x}{2},b=\frac{3x}{2}\)直接验证就好
#include <bits/stdc++.h>
using namespace std;
#define int long long
int read(){...}
void solve(){
int x = read() , a = x / 2 , b = a * 3 ;
if(( a ^ b) != x || a + b != x * 2 ) printf("-1\n");
else printf("%d %d\n" , a , b );
}
int32_t main(){
for( int t = read() ; t ; t -- )
solve();
return 0;
}
F. Timofey and Black-White Tree(补题)
直接bfs,在保证最优性的情况下,层数下降的非常快,大概是\(n\times(\frac11+\frac12+\frac12+\frac14+\frac14+\frac14+\frac14+\frac18 \cdots)\)的情况。知道了这个性质我就想写了一个dfs
#include <bits/stdc++.h>
using namespace std;
int read(){
int x = 0 , f = 1 , ch = getchar();
while( (ch < '0' || ch > '9') && ch != '-' ) ch = getchar();
if( ch == '-' ) f = -1 , ch = getchar();
while( ch >= '0' && ch <= '9' ) x = ( x << 3 ) + ( x << 1 ) + ch - '0' , ch = getchar();
return x * f;
}
int n , ans;
vector<int> c , res , color;
vector<vector<int>> e;
void dfs( int u , int fa , int dis ){
if( dis >= ans ) return;
for( auto v : e[u] ){
if( v == fa ) continue;
if( color[v] == 1 ) {
ans = min( ans , dis + 1 );
return;
}
dfs( v , u , dis + 1 );
}
}
void solve(){
n = read() , ans = INT_MAX;
c = vector<int>(n) , res.clear() , color = vector<int>(n+1 , 0 ) , e = vector<vector<int>>( n+1 );
for( auto &i : c ) i = read();
for( int i = 1 , u , v ; i < n ; i ++ ){
u = read() , v = read();
e[u].push_back(v) , e[v].push_back(u);
}
color[ c[0] ] = 1;
for( int i = 1 ; i < n ; i ++ ){
color[ c[i] ] = 1;
dfs( c[i] , -1 , 0 );
cout << ans << " ";
}
cout << "\n";
}
int32_t main(){
for( int t = read() ; t ; t -- )
solve();
return 0;
}
然后TLE20,觉得可能dfs的问题又写了一下bfs
#include <bits/stdc++.h>
using namespace std;
int read(){
int x = 0 , f = 1 , ch = getchar();
while( (ch < '0' || ch > '9') && ch != '-' ) ch = getchar();
if( ch == '-' ) f = -1 , ch = getchar();
while( ch >= '0' && ch <= '9' ) x = ( x << 3 ) + ( x << 1 ) + ch - '0' , ch = getchar();
return x * f;
}
int n , ans;
vector<int> c , res , color;
vector<vector<int>> e;
#define mp make_pair
void solve(){
n = read() , ans = INT_MAX;
vector<int> c(n) , color( n+1 , 0 );
vector< vector<int> > e(n+1);
for( auto &i : c ) i = read();
for( int i = 1 , u , v ; i < n ; i ++ ){
u = read() , v = read();
e[u].push_back(v) , e[v].push_back(u);
}
color[ c[0] ] = 1;
for( int i = 1 ; i < n ; i ++ ){
color[ c[i] ] = 1;
unordered_set<int> vis;
queue< pair<int,int> > q;
q.push( mp( c[i] , 0 ) ) , vis.insert(c[i]);
while( !q.empty() ){
auto [ u , dis ] = q.front(); q.pop();
if( dis >= ans ) break;
bool flag = false;
for( auto v : e[u] ){
if( vis.count(v) ) continue;
if( color[v] == 1 ) {
ans = min( ans , dis + 1 );
flag = true;
break;
}
q.emplace( v , dis + 1 ) , vis.emplace(v);
}
if( flag ) break;
}
printf("%d " , ans );
}
printf("\n");
return;
}
int32_t main(){
for( int t = read() ; t ; t -- )
solve();
return 0;
}
还是TLE20,我们换个角度来思考一下,只有新增加的点可能会影响答案,所以我们维护一个每个点到黑点的最短距离,没次加入一个点后,用bfs去更像一下整张图的最短距离
#include <bits/stdc++.h>
using namespace std;
int read(){
int x = 0 , f = 1 , ch = getchar();
while( (ch < '0' || ch > '9') && ch != '-' ) ch = getchar();
if( ch == '-' ) f = -1 , ch = getchar();
while( ch >= '0' && ch <= '9' ) x = ( x << 3 ) + ( x << 1 ) + ch - '0' , ch = getchar();
return x * f;
}
int n , ans;
vector<int> c , res , color;
vector<vector<int>> e;
#define mp make_pair
void solve(){
n = read() , ans = INT_MAX;
vector<int> c(n) , color( n+1 , 0 );
vector< vector<int> > e(n+1);
for( auto &i : c ) i = read();
for( int i = 1 , u , v ; i < n ; i ++ ){
u = read() , v = read();
e[u].push_back(v) , e[v].push_back(u);
}
vector<int> dis( n+1 , n );
for( auto i : c ){
ans = min( ans , dis[i] );
if( ans < n ) printf( "%d " , ans );
queue<int> q;
q.push( i ) , dis[i] = 0;
while( !q.empty() ){
auto u = q.front() ; q.pop();
if( dis[u] + 1 >= ans ) break;
for( auto v : e[u] ){
if( dis[u] + 1 >= dis[v] ) continue;
dis[v] = dis[u] + 1 , q.push( v );
}
}
}
printf("\n");
return;
}
int32_t main(){
for( int t = read() ; t ; t -- )
solve();
return 0;
}