A:1210 Chinese Girls' Amusement
大数。如果n%4==0,输出n/2-1,如果n%2==0&&n%4==1,输出n/2-2,如果n%2==1,输出n/2。
#include <cstdio> #include <cstring> #include <algorithm> #include <cmath> using namespace std ; typedef long long LL ; #define rep( i , a , b ) for ( int i = a ; i < b ; ++ i ) #define For( i , a , b ) for ( int i = a ; i <= b ; ++ i ) #define rev( i , a , b ) for ( int i = a ; i >= b ; -- i ) #define travel( e , H , u ) for ( Edge* e = H[u] ; e ; e = e -> next ) #define clr( a , x ) memset ( a , x , sizeof a ) #define cpy( a , x ) memcpy ( a , x , sizeof a ) #define ls ( o << 1 ) #define rs ( o << 1 | 1 ) #define lson ls , l , m #define rson rs , m + 1 , r #define mid ( ( l + r ) >> 1 ) #define root 1 , 1 , n const int MAXN = 100006 ; char s[MAXN] ; int num[MAXN] ; void solve () { int n = strlen ( s ) ; rep ( i , 0 , n ) num[i] = s[i] - '0' ; int flag = num[n - 1] & 1 ; int tmp = 0 ; rep ( i , 0 , n ) { num[i] += tmp * 10 ; tmp = num[i] % 2 ; num[i] /= 2 ; } if ( flag == 1 ) { if ( num[0] ) printf ( "%d" , num[0] ) ; rep ( i , 1 , n ) printf ( "%d" , num[i] ) ; printf ( "\n" ) ; } else { int del = 1 ; rev ( i , n - 1 , 0 ) { del = num[i] - del ; num[i] = del ; del = 0 ; if ( num[i] < 0 ) { num[i] += 10 ; del = 1 ; } } if ( ( num[n - 1] & 1 ) == 0 ) { int del = 1 ; rev ( i , n - 1 , 0 ) { del = num[i] - del ; num[i] = del ; del = 0 ; if ( num[i] < 0 ) { num[i] += 10 ; del = 1 ; } } } if ( num[0] ) printf ( "%d" , num[0] ) ; rep ( i , 1 , n ) printf ( "%d" , num[i] ) ; printf ( "\n" ) ; } } int main () { while ( gets ( s ) ) solve () ; return 0 ; }
B:1211 Reactor Cooling
裸的带下界的可行流。
#include <cstdio> #include <cstring> #include <algorithm> #include <cmath> using namespace std ; typedef long long LL ; #define rep( i , a , b ) for ( int i = a ; i < b ; ++ i ) #define For( i , a , b ) for ( int i = a ; i <= b ; ++ i ) #define rev( i , a , b ) for ( int i = a ; i >= b ; -- i ) #define travel( e , H , u ) for ( Edge* e = H[u] ; e ; e = e -> next ) #define clr( a , x ) memset ( a , x , sizeof a ) #define cpy( a , x ) memcpy ( a , x , sizeof a ) #define ls ( o << 1 ) #define rs ( o << 1 | 1 ) #define lson ls , l , m #define rson rs , m + 1 , r #define mid ( ( l + r ) >> 1 ) #define root 1 , 1 , n const int MAXN = 205 ; const int MAXE = 1000000 ; const int INF = 0x3f3f3f3f ; struct Edge { int v , c , n ; Edge () {} Edge ( int v , int c , int n ) : v ( v ) , c ( c ) , n ( n ) {} } E[MAXE] ; int H[MAXN] , cntE ; int d[MAXN] , cur[MAXN] , pre[MAXN] , num[MAXN] ; int Q[MAXN] , head , tail ; int s , t , nv ; int flow ; int n , m ; int in[MAXN] , ou[MAXN] ; int low[MAXE] ; void clear () { cntE = 0 ; clr ( H , -1 ) ; clr ( in , 0 ) ; clr ( ou , 0 ) ; } void addedge ( int u , int v , int c ) { E[cntE] = Edge ( v , c , H[u] ) ; H[u] = cntE ++ ; E[cntE] = Edge ( u , 0 , H[v] ) ; H[v] = cntE ++ ; } void rev_bfs () { clr ( d , -1 ) ; clr ( num , 0 ) ; head = tail = 0 ; Q[tail ++] = t ; d[t] = 0 ; num[0] = 1 ; while ( head != tail ) { int u = Q[head ++] ; for ( int i = H[u] ; ~i ; i = E[i].n ) { int v = E[i].v ; if ( ~d[v] ) continue ; d[v] = d[u] + 1 ; num[d[v]] ++ ; Q[tail ++] = v ; } } } int ISAP () { rev_bfs () ; cpy ( cur , H ) ; flow = 0 ; int u = pre[s] = s , i , pos , f , minv ; while ( d[s] < nv ) { if ( u == t ) { f = INF ; for ( i = s ; i != t ; i = E[cur[i]].v ) { if ( f > E[cur[i]].c ) { f = E[cur[i]].c ; pos = i ; } } for ( i = s ; i != t ; i = E[cur[i]].v ) { E[cur[i]].c -= f ; E[cur[i] ^ 1].c += f ; } flow += f ; u = pos ; } for ( i = cur[u] ; ~i ; i = E[i].n ) { if ( E[i].c && d[u] == d[E[i].v] + 1 ) break ; } if ( ~i ) { cur[u] = i ; pre[E[i].v] = u ; u = E[i].v ; } else { if ( 0 == --num[d[u]] ) break ; for ( minv = nv , i = H[u] ; ~i ; i = E[i].n ) { if ( E[i].c && minv > d[E[i].v] ) { minv = d[E[i].v] ; cur[u] = i ; } } d[u] = minv + 1 ; num[d[u]] ++ ; u = pre[u] ; } } return flow ; } void solve () { int u , v , c ; clear () ; s = 0 ; t = n + 1 ; nv = t + 1 ; rep ( i , 0 , m ) { scanf ( "%d%d%d%d" , &u , &v , &low[i] , &c ) ; in[v] += low[i] ; ou[u] += low[i] ; addedge ( u , v , c - low[i] ) ; } For ( i , 1 , n ) { int tmp = in[i] - ou[i] ; if ( tmp > 0 ) addedge ( s , i , tmp ) ; if ( tmp < 0 ) addedge ( i , t , -tmp ) ; } ISAP () ; int ok = 1 ; for ( int i = H[s] ; ~i ; i = E[i].n ) if ( E[i].c ) ok = 0 ; if ( ok == 0 ) { printf ( "NO\n" ) ; } else { printf ( "YES\n" ) ; rep ( i , 0 , m ) printf ( "%d\n" , low[i] + E[i << 1 | 1].c ) ; } } int main () { while ( ~scanf ( "%d%d" , &n , &m ) ) solve () ; return 0 ; }
D:1213 Matrix Multiplication
所有边的两个点的度之和即答案。观察找规律可知,两个矩阵相乘时如果对应位置为1则必定是两条线段有公共点。
#include <cstdio> #include <cstring> #include <algorithm> #include <cmath> using namespace std ; typedef long long LL ; #define rep( i , a , b ) for ( int i = a ; i < b ; ++ i ) #define For( i , a , b ) for ( int i = a ; i <= b ; ++ i ) #define rev( i , a , b ) for ( int i = a ; i >= b ; -- i ) #define travel( e , H , u ) for ( Edge* e = H[u] ; e ; e = e -> next ) #define clr( a , x ) memset ( a , x , sizeof a ) #define cpy( a , x ) memcpy ( a , x , sizeof a ) #define ls ( o << 1 ) #define rs ( o << 1 | 1 ) #define lson ls , l , m #define rson rs , m + 1 , r #define mid ( ( l + r ) >> 1 ) #define root 1 , 1 , n const int MAXN = 10005 ; const int MAXE = 100005 ; struct Seg { int u , v ; } seg[MAXE] ; int num[MAXN] ; int n , m ; void solve () { clr ( num , 0 ) ; rep ( i , 0 , m ) { scanf ( "%d%d" , &seg[i].u , &seg[i].v ) ; num[seg[i].u] ++ ; num[seg[i].v] ++ ; } LL ans = 0 ; rep ( i , 0 , m ) { ans += num[seg[i].u] ; ans += num[seg[i].v] ; } printf ( "%lld\n" , ans ) ; } int main () { while ( ~scanf ( "%d%d" , &n , &m ) ) solve () ; return 0 ; }
E:1214 Nice Patterns Strike Back
因为下一列只与上一列的状态有关,可以暴力判断预处理出转移矩阵。高精度+矩阵快速幂,比赛的时候高精度写错了,蛋疼死。。
#include <cstdio> #include <cstring> #include <algorithm> #include <cmath> using namespace std ; typedef long long LL ; #define rep( i , a , b ) for ( int i = a ; i < b ; ++ i ) #define For( i , a , b ) for ( int i = a ; i <= b ; ++ i ) #define rev( i , a , b ) for ( int i = a ; i >= b ; -- i ) #define travel( e , H , u ) for ( Edge* e = H[u] ; e ; e = e -> next ) #define clr( a , x ) memset ( a , x , sizeof a ) #define cpy( a , x ) memcpy ( a , x , sizeof a ) #define ls ( o << 1 ) #define rs ( o << 1 | 1 ) #define lson ls , l , m #define rson rs , m + 1 , r #define mid ( ( l + r ) >> 1 ) #define root 1 , 1 , cnt const int M = 50 ; const int L = 10 ; int mod ; struct BigInt { int digit[1005] ; int length ; BigInt () {} BigInt ( char buf[] ) : length ( 0 ) { clr ( digit , 0 ) ; length = strlen ( buf ) ; rep ( i , 0 , length ) digit[i] = buf[length - i - 1] - '0' ; } int operator [] ( const int& index ) const { return digit[index] ; } int& operator [] ( const int& index ) { return digit[index] ; } BigInt fix () { while ( length && digit[length - 1] == 0 ) -- length ; return *this ; } BigInt operator / ( const int& b ) { BigInt c ; c.length = length ; int tmp = 0 ; rev ( i , length - 1 , 0 ) { c[i] = digit[i] + tmp * 10 ; tmp = c[i] % b ; c[i] /= b ; } return c.fix () ; } BigInt operator - ( const int& b ) { BigInt c ; c.length = length ; int tmp = b ; rep ( i , 0 , length ) { tmp = digit[i] - tmp ; c[i] = tmp ; tmp = 0 ; if ( c[i] < 0 ) { c[i] += 10 ; tmp = 1 ; } } return c.fix () ; } void show () { if ( length == 0 ) { printf ( "0\n" ) ; return ; } printf ( "%d" , digit[length - 1] ) ; rev ( i , length - 2 , 0 ) printf ( "%d" , digit[i] ) ; printf ( "\n" ) ; } } ; struct Matrix { int mat[M][M] ; int n ; Matrix () { clr ( mat , 0 ) ; } Matrix ( int n ) : n ( n ) { clr ( mat , 0 ) ; } void eyes () { clr ( mat , 0 ) ; rep ( i , 0 , n ) mat[i][i] = 1 ; } void empty () { clr ( mat , 0 ) ; } Matrix operator * ( const Matrix& a ) const { Matrix c ( n ) ; rep ( i , 0 , n ) rep ( j , 0 , n ) rep ( k , 0 , n ) { c.mat[i][j] = ( c.mat[i][j] + mat[i][k] * a.mat[k][j] ) % mod ; } return c ; } void show () { rep ( i , 0 , n ) { rep ( j , 0 , n ) printf ( "%d " , mat[i][j] ) ; printf ( "\n" ) ; } } } ; Matrix A[6] ; char buf[500] ; int m ; int check ( int a , int b , int n ) { int cnt1 = 0 ; int cnt2 = 0 ; rep ( i , 0 , n ) { if ( a % 2 == 0 && b % 2 == 0 ) { cnt1 ++ ; cnt2 = 0 ; if ( cnt1 == 2 ) return 0 ; } else if ( a % 2 == 1 && b % 2 == 1 ) { cnt2 ++ ; cnt1 = 0 ; if ( cnt2 == 2 ) return 0 ; } else cnt1 = cnt2 = 0 ; a >>= 1 ; b >>= 1 ; } return 1 ; } void fun () { For ( i , 1 , 5 ) { int S = 1 << i ; A[i].n = S ; A[i].empty () ; rep ( j , 0 , S ) { rep ( k , 0 , S ) { if ( check ( j , k , i ) ) A[i].mat[j][k] = 1 ; } } } } Matrix pow ( Matrix& a , BigInt& b ) { Matrix res ( a.n ) ; Matrix tmp = a ; res.eyes () ; while ( b.length ) { if ( b[0] & 1 ) res = res * tmp ; tmp = tmp * tmp ; b = b / 2 ; } return res ; } void solve () { BigInt c ( buf ) ; c = c - 1 ; Matrix res = pow ( A[m] , c ) ; int S = 1 << m ; int ans = 0 ; rep ( i , 0 , S ) rep ( j , 0 , S ) ans = ( ans + res.mat[i][j] ) % mod ; printf ( "%d\n" , ans ) ; } int main () { fun () ; while ( ~scanf ( "%s%d%d" , buf , &m ,&mod ) ) solve () ; return 0 ; }
G:1216 Beautiful People
线段树优化DP。
先将所有点按照第一个关键字排序,将第二个关键字离散化。然后按第一关键字从小到大扫所有的人,一段一段的更新第一关键字相同的。每一段相同关键字的人用query求出他的最优值,以及最优值对应的id,然后更新前驱,接下来用栈保存他的信息,直到所有第一关键字相同的人都查询完后,再将栈中保存的信息用以更新线段树,线段树中以b作为下标,每个区间保存这个区间的最大单调子序列的长度以及结尾元素的id。
#include <cstdio> #include <cstring> #include <algorithm> #include <cmath> using namespace std ; typedef long long LL ; #define rep( i , a , b ) for ( int i = a ; i < b ; ++ i ) #define For( i , a , b ) for ( int i = a ; i <= b ; ++ i ) #define rev( i , a , b ) for ( int i = a ; i >= b ; -- i ) #define travel( e , H , u ) for ( Edge* e = H[u] ; e ; e = e -> next ) #define clr( a , x ) memset ( a , x , sizeof a ) #define cpy( a , x ) memcpy ( a , x , sizeof a ) #define ls ( o << 1 ) #define rs ( o << 1 | 1 ) #define lson ls , l , m #define rson rs , m + 1 , r #define mid ( ( l + r ) >> 1 ) #define root 1 , 1 , cnt const int MAXN = 300005 ; struct Node { int a , b , idx ; bool operator < ( const Node& t ) const { return a < t.a ; } } node[MAXN] ; struct Stack { int pos , max , idx ; Stack () {} Stack ( int pos , int max , int idx ) : pos ( pos ) , max ( max ) , idx ( idx ) {} } S[MAXN] ; int top ; int pre[MAXN] ; int maxv[MAXN << 2] ; int idx[MAXN << 2] ; int a[MAXN] , cnt ; int n ; int unique ( int n ) { int cnt = 1 ; sort ( a + 1 , a + n + 1 ) ; For ( i , 2 , n ) if ( a[i] != a[cnt] ) a[++ cnt] = a[i] ; return cnt ; } int hash ( int x ) { int l = 1 , r = cnt ; while ( l < r ) { int m = ( l + r ) >> 1 ; if ( a[m] >= x ) r = m ; else l = m + 1 ; } return l ; } void update ( int x , int _max , int _idx , int o , int l , int r ) { while ( l < r ) { int m = ( l + r ) >> 1 ; if ( x <= m ) { o = o << 1 ; r = m ; } else { o = o << 1 | 1 ; l = m + 1 ; } } maxv[o] = _max ; idx[o] = _idx ; while ( o > 1 ) { o >>= 1 ; if ( maxv[ls] > maxv[rs] ) { maxv[o] = maxv[ls] ; idx[o] = idx[ls] ; } else { maxv[o] = maxv[rs] ; idx[o] = idx[rs] ; } } } int query_idx , query_max ; int stack[MAXN] ; void query ( int L , int R , int o , int l , int r ) { if ( L > R ) return ; if ( L <= l && r <= R ) { if ( query_max < maxv[o] ) { query_max = maxv[o] ; query_idx = idx[o] ; } return ; } int m = mid ; if ( L <= m ) query ( L , R , lson ) ; if ( m < R ) query ( L , R , rson ) ; } void solve () { cnt = 0 ; clr ( pre , 0 ) ; clr ( maxv , 0 ) ; clr ( idx , 0 ) ; For ( i , 1 , n ) { scanf ( "%d%d" , &node[i].a , &node[i].b ) ; node[i].idx = i ; a[++ cnt] = node[i].b ; } cnt = unique ( cnt ) ; sort ( node + 1 , node + n + 1 ) ; For ( i , 1 , n ) { int j = i ; top = 0 ; while ( j <= n && node[i].a == node[j].a ) { query_idx = 0 ; query_max = 0 ; int R = hash ( node[j].b ) ; query ( 1 , R - 1 , root ) ; pre[node[j].idx] = query_idx ; S[top ++] = Stack ( R , query_max + 1 , node[j].idx ) ; //printf ( "%d %d %d\n" , R , query_max + 1 , j ) ; ++ j ; } rep ( k , 0 , top ) update ( S[k].pos , S[k].max , S[k].idx , root ) ; i = j - 1 ; } printf ( "%d\n" , maxv[1] ) ; top = 0 ; for ( int i = idx[1] ; i ; i = pre[i] ) { stack[top ++] = i ; } sort ( stack , stack + top ) ; rep ( i , 0 , top ) printf ( "%d%c" , stack[i] , i < top - 1 ? ' ' : '\n' ) ; } int main () { scanf ( "%d" , &n ) ; solve () ; return 0 ; }