生活随笔
收集整理的這篇文章主要介紹了
Codeforces Round #698 (Div. 2)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
B題 題意:定義一個牛逼的數是這個數十進制中至少包含一個數d。 現在給定d和若干詢問,每個詢問一個x,問x能否分解成若干d構成的牛逼的數之和。 看起來挺難搞的,不能快速的判斷是否是牛逼的數而且也不能很好的挑選合適的數組成x。那么我們不妨就把這個數拆成 a%d + a/d*d ,這樣只需要判斷a%d變成牛逼數加的d的最少數量,讓后跟a/d比較一下大小就可以了。這個東西是可以預處理出來的,具體可以看代碼。
#include <cstdio>
#include <iostream>
#include <string>
#include <cstring>
#include <map>
#include <cmath>
#include <cctype>
#include <vector>
#include <set>
#include <queue>
#include <algorithm>
#include <sstream>
#include <ctime>
#include <cstdlib>
#define X first
#define Y second
#define L (u<<1)
#define R (u<<1|1)
#define pb push_back
#define mk make_pair
#define Mid (tr[u].l+tr[u].r>>1)
#define Len(u) (tr[u].r-tr[u].l+1)
#define random(a,b) ((a)+rand()%((b)-(a)+1))
#define db puts("---")
using namespace std
;
typedef long long LL
;
typedef unsigned long long ULL
;
typedef pair
< int , int > PII
; const int N
= 1000010 , mod
= 1e9 + 7 , INF
= 0x3f3f3f3f ;
const double eps
= 1e-6 ; int n
;
int f
[ 20 ] [ 20 ] ; bool check ( int x
, int d
)
{ while ( x
) { if ( x
% 10 == d
) return true ; x
/ = 10 ; } return false ;
} void init ( )
{ for ( int i
= 1 ; i
<= 9 ; i
++ ) { for ( int j
= 1 ; j
<= 9 ; j
++ ) { int sum
= i
, cnt
= 0 ; while ( ! check ( sum
, j
) ) sum
+ = j
, cnt
++ ; f
[ i
] [ j
] = cnt
; } }
} int main ( )
{
init ( ) ; int _
; cin
>> _
; while ( _
-- ) { int q
, d
; scanf ( "%d%d" , & q
, & d
) ; while ( q
-- ) { int x
; scanf ( "%d" , & x
) ; int a
= x
% d
, b
= x
/ d
; if ( f
[ a
] [ d
] <= b
) puts ( "YES" ) ; else puts ( "NO" ) ; } } return 0 ;
}
C題 題意: 數組a是一個特定的數組,對于每個數 a 都有一個相反數 - a 。讓后定義 d 為上面的式子,我們發現對于每個數他的相反數和這個數的 d 是相同的,所以我們只需要先排序檢查一下是否符合,讓后處理正數即可。化簡式子可得 讓后 an 可以直接算出來,依次遞推 a ( n - 1 ) ,讓后檢查是否符合即可。
#include <cstdio>
#include <iostream>
#include <string>
#include <cstring>
#include <map>
#include <cmath>
#include <cctype>
#include <vector>
#include <set>
#include <queue>
#include <algorithm>
#include <sstream>
#include <ctime>
#include <cstdlib>
#define X first
#define Y second
#define L (u<<1)
#define R (u<<1|1)
#define pb push_back
#define mk make_pair
#define Mid (tr[u].l+tr[u].r>>1)
#define Len(u) (tr[u].r-tr[u].l+1)
#define random(a,b) ((a)+rand()%((b)-(a)+1))
#define db puts("---")
using namespace std
;
typedef long long LL
;
typedef unsigned long long ULL
;
typedef pair
< int , int > PII
; const int N
= 1000010 , mod
= 1e9 + 7 , INF
= 0x3f3f3f3f ;
const double eps
= 1e-6 ; int n
;
LL a
[ N
] , d
[ N
] ; bool check ( )
{ for ( int i
= 1 ; i
<= n
* 2 ; i
+ = 2 ) if ( d
[ i
] != d
[ i
+ 1 ] ) return false ; if ( d
[ n
* 2 ] % ( n
* 2 ) != 0 ) return false ; a
[ n
] = d
[ n
* 2 ] / ( n
* 2 ) ; for ( int i
= n
- 1 ; i
>= 1 ; i
-- ) { LL x
= d
[ i
* 2 + 1 ] , y
= d
[ i
* 2 ] ; if ( ( x
- y
) % ( 2 * i
) != 0 ) return false ; a
[ i
] = a
[ i
+ 1 ] - ( x
- y
) / ( 2 * i
) ; if ( a
[ i
] >= a
[ i
+ 1 ] || a
[ i
] <= 0 ) return false ; } return true ;
} int main ( )
{
int _
; scanf ( "%d" , & _
) ; while ( _
-- ) { scanf ( "%d" , & n
) ; for ( int i
= 1 ; i
<= n
* 2 ; i
++ ) scanf ( "%lld" , & d
[ i
] ) ; sort ( d
+ 1 , d
+ 1 + n
* 2 ) ; if ( ! check ( ) ) puts ( "NO" ) ; else puts ( "YES" ) ; } return 0 ;
}
D.
題意: 給定一個數組,可以做無數次操作,每次操作任選兩個數 x 和 y,讓后在后面添加 2 * x - y。問能否得到k。 我們把 2 * x - y 拆成 x + ( x - y ) ,這樣就相當于在一個數后面加上這個數與任意數的差。既然這樣我們可以思考能否通過一個選定的數,讓后加上這個數與其他數的差來得到 k 呢?所以我們多寫幾組就可以發現每個數都可以寫成 ah+∑i,j(ai?aj)a_h + \sum_{i,j} (a_i-a_j) a h ? + i , j ∑ ? ( a i ? ? a j ? ) 其中 i j 是任選的兩個數。那么我們的 k 也是可以寫成這種形式的,換句話說就是ah+∑i,j(ai?aj)=ka_h + \sum_{i,j} (a_i-a_j) = k a h ? + i , j ∑ ? ( a i ? ? a j ? ) = k 我們需要移一下項∑i,j(ai?aj)=k?ah\sum_{i,j} (a_i-a_j) = k - a_h i , j ∑ ? ( a i ? ? a j ? ) = k ? a h ? 現在我們考慮如何確定 h i j 呢?我們可以發現對于每一個數我們都可以通過兩次操作變成另一個。比如我們現在有 ana_n a n ? ,讓后我們需要得到a1a_1 a 1 ? 。我們只需要先得到an+(an?a1)a_n+(a_n-a_1) a n ? + ( a n ? ? a 1 ? ) ,讓后an+(an?(an+(an?a1)))a_n+(a_n-(a_n+(a_n-a_1))) a n ? + ( a n ? ? ( a n ? + ( a n ? ? a 1 ? ) ) ) 即可得到a1a_1 a 1 ? 。所以我們可以把 aja_j a j ? 和 aha_h a h ? 統一成 a1a_1 a 1 ? ,讓后就得到如下式子∑i,1(ai?a1)=k?a1\sum_{i,1} (a_i-a_1) = k - a_1 i , 1 ∑ ? ( a i ? ? a 1 ? ) = k ? a 1 ? ,讓后顯然有解的條件是(k?a1)modgcd?(ai,a1)==0(k-a_1) \bmod \gcd(a_i,a_1) == 0 ( k ? a 1 ? ) m o d g cd( a i ? , a 1 ? ) = = 0 ,讓后一層循環跑一遍就可以啦。
#include <cstdio>
#include <iostream>
#include <string>
#include <cstring>
#include <map>
#include <cmath>
#include <cctype>
#include <vector>
#include <set>
#include <queue>
#include <algorithm>
#include <sstream>
#include <ctime>
#include <cstdlib>
#define X first
#define Y second
#define L (u<<1)
#define R (u<<1|1)
#define pb push_back
#define mk make_pair
#define Mid (tr[u].l+tr[u].r>>1)
#define Len(u) (tr[u].r-tr[u].l+1)
#define random(a,b) ((a)+rand()%((b)-(a)+1))
#define db puts("---")
using namespace std
;
typedef long long LL
;
typedef unsigned long long ULL
;
typedef pair
< int , int > PII
; const int N
= 1000010 , mod
= 1e9 + 7 , INF
= 0x3f3f3f3f ;
const double eps
= 1e-6 ; int n
;
int a
[ N
] ; int main ( )
{
int _
; scanf ( "%d" , & _
) ; while ( _
-- ) { LL k
; scanf ( "%d%lld" , & n
, & k
) ; LL gd
= 0 , first
= - 1000000000000000001 ; for ( int i
= 1 ; i
<= n
; i
++ ) { LL x
; scanf ( "%lld" , & x
) ; if ( first
== - 1000000000000000001 ) first
= x
; else gd
= __gcd ( gd
, x
- first
) ; } if ( ( k
- first
) % gd
== 0 ) puts ( "YES" ) ; else puts ( "NO" ) ; } return 0 ;
}
E. 題意:給定兩個串 a b,讓后有q個操作,每個操作對應一個區間,讓后你首先需要檢查這個區間是否全為0或1,如果不是就退出。否則你可以選擇修改嚴格小于 長度 / 2 個數。問最終能否使 a 變成 b 。 正著來很難想,因為每次都需要先看是否全為0或者1,讓后修改,而且修改還需要顧及下面的操作能否滿足全為0或1,所以我們考慮全部反著來。反著來也就是由b到a,每次先修改嚴格小于 長度 / 2 個數,讓后使其全為0或1。這樣就很簡單了,每次只需要修改數量少的哪個就可以了,需要特判一下兩者相等的情況,這樣的話不能修改直接輸出No即可。最后檢查一下是否變成了a就行啦。 對于兩個操作直接用線段樹維護就好啦,線段樹的基本操作了。
#include <cstdio>
#include <iostream>
#include <string>
#include <cstring>
#include <map>
#include <cmath>
#include <cctype>
#include <vector>
#include <set>
#include <queue>
#include <algorithm>
#include <sstream>
#include <ctime>
#include <cstdlib>
#define X first
#define Y second
#define L (u<<1)
#define R (u<<1|1)
#define pb push_back
#define mk make_pair
#define Mid (tr[u].l+tr[u].r>>1)
#define Len(u) (tr[u].r-tr[u].l+1)
#define random(a,b) ((a)+rand()%((b)-(a)+1))
#define db puts("---")
using namespace std
;
typedef long long LL
;
typedef unsigned long long ULL
;
typedef pair
< int , int > PII
; const int N
= 200010 , mod
= 1e9 + 7 , INF
= 0x3f3f3f3f ;
const double eps
= 1e-6 ; int n
, m
;
char st
[ N
] , ed
[ N
] ;
PII q
[ N
] ;
struct Node
{ int l
, r
; int sum
, lazy
;
} tr
[ N
<< 2 ] ; void pushup ( int u
)
{ tr
[ u
] . sum
= tr
[ L
] . sum
+ tr
[ R
] . sum
;
} void pushdown ( int u
)
{ if ( tr
[ u
] . lazy
== - 1 ) return ; tr
[ L
] . lazy
= tr
[ u
] . lazy
; tr
[ R
] . lazy
= tr
[ u
] . lazy
; tr
[ L
] . sum
= Len ( L
) * tr
[ u
] . lazy
; tr
[ R
] . sum
= Len ( R
) * tr
[ u
] . lazy
; tr
[ u
] . lazy
= - 1 ;
} void build ( int u
, int l
, int r
)
{ tr
[ u
] = { l
, r
, 0 , - 1 } ; if ( l
== r
) { tr
[ u
] . sum
+ = ed
[ l
] - '0' ; return ; } build ( L
, l
, Mid
) ; build ( R
, Mid
+ 1 , r
) ; pushup ( u
) ;
} void modify ( int u
, int l
, int r
, int c
)
{ if ( tr
[ u
] . l
>= l
&& tr
[ u
] . r
<= r
) { tr
[ u
] . sum
= Len ( u
) * c
; tr
[ u
] . lazy
= c
; return ; } pushdown ( u
) ; if ( l
<= Mid
) modify ( L
, l
, r
, c
) ; if ( r
> Mid
) modify ( R
, l
, r
, c
) ; pushup ( u
) ;
} int query ( int u
, int l
, int r
)
{ if ( tr
[ u
] . l
>= l
&& tr
[ u
] . r
<= r
) return tr
[ u
] . sum
; pushdown ( u
) ; int ans
= 0 ; if ( l
<= Mid
) ans
+ = query ( L
, l
, r
) ; if ( r
> Mid
) ans
+ = query ( R
, l
, r
) ; return ans
;
} bool check ( )
{ for ( int i
= m
; i
>= 1 ; i
-- ) { int l
= q
[ i
] . X
, r
= q
[ i
] . Y
; int sum
= query ( 1 , l
, r
) , len
= r
- l
+ 1 ; if ( len
% 2 == 0 && sum
* 2 == len
) return false ; if ( len
- sum
> sum
) modify ( 1 , l
, r
, 0 ) ; else modify ( 1 , l
, r
, 1 ) ; } for ( int i
= 1 ; i
<= n
; i
++ ) if ( query ( 1 , i
, i
) != st
[ i
] - '0' ) return false ; return true ;
} int main ( )
{
int _
; scanf ( "%d" , & _
) ; while ( _
-- ) { scanf ( "%d%d" , & n
, & m
) ; scanf ( "%s%s" , st
+ 1 , ed
+ 1 ) ; build ( 1 , 1 , n
) ; for ( int i
= 1 ; i
<= m
; i
++ ) scanf ( "%d%d" , & q
[ i
] . X
, & q
[ i
] . Y
) ; if ( check ( ) ) puts ( "YES" ) ; else puts ( "NO" ) ; } return 0 ;
}
F. 題意:給n個點,讓你求這n個點一個排列,使得相鄰的三個之間構成的角為銳角。 我們可以發現當是鈍角的時候,鈍角對的邊一定是最大的。那么我們可以考慮一個貪心策略,我們每次都找距離當前點最遠的點,讓后把他們倆連起來的邊當坐角邊,而非對角邊。 下面證明一下: 假設當前有三個點 A B C ,目前知道距離A最遠的點為B,距離B最遠的點為C,可以得知AC<AB,所以ABC構成的三角形中最長邊為角邊,所以∠ABC一定不是鈍角。 讓后直接瞎搞搞就可以啦。 為了避免精度問題,所以距離最好不開方。
#include <cstdio>
#include <iostream>
#include <string>
#include <cstring>
#include <map>
#include <cmath>
#include <cctype>
#include <vector>
#include <set>
#include <queue>
#include <algorithm>
#include <sstream>
#include <ctime>
#include <cstdlib>
#define X first
#define Y second
#define L (u<<1)
#define R (u<<1|1)
#define pb push_back
#define mk make_pair
#define Mid (tr[u].l+tr[u].r>>1)
#define Len(u) (tr[u].r-tr[u].l+1)
#define random(a,b) ((a)+rand()%((b)-(a)+1))
#define db puts("---")
using namespace std
;
typedef long long LL
;
typedef unsigned long long ULL
;
typedef pair
< LL
, LL
> PII
; const int N
= 1000010 , mod
= 1e9 + 7 , INF
= 0x3f3f3f3f ;
const double eps
= 1e-6 ; int n
;
int ans
[ N
] , st
[ N
] ;
PII p
[ N
] ; LL
get ( int i
, int j
)
{ LL dx
= p
[ i
] . X
- p
[ j
] . X
; LL dy
= p
[ i
] . Y
- p
[ j
] . Y
; return dx
* dx
+ dy
* dy
;
} int main ( )
{
scanf ( "%d" , & n
) ; for ( int i
= 1 ; i
<= n
; i
++ ) scanf ( "%lld%lld" , & p
[ i
] . X
, & p
[ i
] . Y
) ; ans
[ 1 ] = 1 , st
[ 1 ] = 1 ; for ( int i
= 1 ; i
<= n
- 1 ; i
++ ) { LL mx
= 0 , id
= - 1 ; for ( int j
= 1 ; j
<= n
; j
++ ) if ( ! st
[ j
] && get ( ans
[ i
] , j
) > mx
) mx
= get ( ans
[ i
] , j
) , id
= j
; ans
[ i
+ 1 ] = id
; st
[ id
] = 1 ; } for ( int i
= 1 ; i
<= n
; i
++ ) printf ( "%d " , ans
[ i
] ) ; puts ( "" ) ; return 0 ;
}
總結
以上是生活随笔 為你收集整理的Codeforces Round #698 (Div. 2) 的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔 網站內容還不錯,歡迎將生活随笔 推薦給好友。