BUCOJ周賽5題解
阿新 • • 發佈:2021-10-23
A
簽到題
#include <bits/stdc++.h>
using namespace std;
int a , b ;
int main()
{
cin >> a >> b;
if( a < b ) puts("0");
else puts("10");
}
B
列舉即可,判斷特殊情況恰好跳到x
和根本跳不到x
#include<bits/stdc++.h> using namespace std; int main() { int n , m ; cin >> n >> m; int ans = 0; for( int i = 1 , x ; i <= n ; i ++ ) { cin >> x; ans += x; if( ans < m ) continue; else if( ans == m ) cout << i + 1 << endl; else cout << i << endl; return 0; } cout << n + 1 << endl; }
C
多畫幾次就會發現一定可以分成一半一半
如果(x,y)
在兩條對角線的焦點上有無數種情況,反之只有(x,y)
與對角線交點連線這一種情況
#include <bits/stdc++.h>; using namespace std; double n , m , a , b; int main() { cin >> n >> m >> a >> b; printf("%.6lf " , n * m / 2 ); if( a == n / 2 && b == m / 2 ) cout << 1 << endl; else cout << 0 << endl; }
D
二分 字首和
如果[l,r]
滿足,則[l,r+1]
也滿足一直到[l,n]
全部都滿足
#include <bits/stdc++.h> using namespace std; #define ll long long const int N = 1e5 + 5; int n ; ll a[N] , cnt , k ; inline ll read() { ll x = 0; char ch = getchar(); while( ch < '0' || ch > '9' ) ch = getchar(); while( ch >= '0' && ch <= '9' ) x = ( x << 3 ) + ( x << 1 ) + ch - '0' , ch = getchar(); return x; } int main() { n = read() , k = read(); for( int i = 1 ; i <= n ; i ++ ) a[i] = a[ i - 1 ] + read(); for( int i = 1 , x ; i <= n ; i ++ ) { if( a[n] - a[ i - 1 ] < k ) break; cnt += n - ( lower_bound( a + 1 , a + 1 + n , a[ i - 1 ] + k ) - a ) + 1; } cout << cnt << endl; return 0; }
E
動態規劃
設f[i][j]
為S到i,T到j有多少個公共子串若s[i]==t[i]
,i-1
、j-1
任意一個子串都可以
f[i][j] =f[i-1][j-1] + f[i-1][j]+f[i][j-1]-f[i-1][j-1]+1
若不相等,則是s[i]
和t[j]
不能同時選
f[i][j]=f[i-1][j]+f[i][j-1]-f[i-1][j-1]
#include <bits/stdc++.h>
using namespace std;
const int N = 2e3 + 50 , Mod = 1e9 + 7;
int n , m , a[N] , b[N] ;
long long f[N][N];
signed main()
{
cin >> n >> m;
for( int i = 1 ; i <= n ; i ++ ) cin >> a[i];
for( int i = 1 ; i <= m ; i ++ ) cin >> b[i];
for( int i = 1 ; i <= n ; i ++ )
{
for( int j = 1 ; j <= m ; j ++ )
{
if( a[i] == b[j] ) f[i][j] = f[ i - 1 ][j] + f[i][ j - 1 ] + 1;
else f[i][j] = f[ i - 1 ][j] + f[i][ j - 1 ] - f[ i - 1 ][ j - 1 ];
f[i][j] %= Mod;
}
}
cout << ( f[n][m] + 1 + Mod ) % Mod << endl;
return 0;
}
F
時間限制是100s,然後手掌面積是一個單峰函式,用三分法列舉即可
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 5 ;
const int dx[] = { 0 , 1 , -1 , 0 , 0 } , dy[] = { 0 , 0 , 0 , 1 , -1 };
int n ;
struct node
{
double x , y;
int dir;
}a[N];
inline int read()
{
int x = 0 , f = 1;
char 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;
}
inline int getdir()
{
char c = getchar();
while( c != 'R' && c != 'L' && c != 'D' && c != 'U' ) c = getchar();
// R L D U
// 1 2 3 4
if( c == 'R' ) return 1;
if( c == 'L' ) return 2;
if( c == 'U' ) return 3;
if( c == 'D' ) return 4;
}
inline double f( double x )
{
double maxx = -1e10 , minx = 1e10 , maxy = -1e10 , miny = 1e10 , tx , ty;
for( int i = 1 ; i <= n ; i ++ )
{
tx = a[i].x + x * dx[ a[i].dir ] , ty = a[i].y + x * dy[ a[i].dir ];
maxx = max( maxx , tx ) , maxy = max( maxy ,ty ) , minx = min( minx , tx ) , miny = min( miny , ty );
}
return ( maxx - minx ) * ( maxy - miny );
}
int main()
{
n = read();
for( int i = 1 ; i <= n ; i ++ ) a[i].x = read() , a[i].y = read() , a[i].dir = getdir();
double l = 0 , r = 1e12 , ans = 1e18;
for( int i = 0 ; i < 300 ; i ++ )
{
double ml = l + ( r - l ) / 3 , mr = l + 2 * ( r - l ) / 3;
double ansl = f( ml ) , ansr = f( mr );
if( ansl > ansr ) l = ml;
else r = mr ;
ans = min( { ans , ansl , ansr } );
}
printf("%.6lf\n" , ans );
return 0;
}