CF1461
CF1461
String Generation
\(k\) 是没有用的 直接按照 \(abc\) 的顺序输出即可
#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define inl inline
#define eb emplace_back
#define mid (l+r>>1)
#define ls p<<1
#define rs p<<1|1
#define lson ls,l,mid
#define rson rs,mid+1,r
#define getchar() cin.get()
#define print(x) cout<<#x<<'='<<x<<endl
#define int long long
const int N = 1e6 + 5;
const int inf = 0x3f3f3f3f;
int read()
{
int f = 1 , x = 0;
char ch = getchar();
while ( !isdigit(ch) ) { if ( ch == '-' ) f = -1; ch = getchar(); }
while ( isdigit(ch) ) { x = ( x << 1 ) + ( x << 3 ) + ( ch ^ 48 ); ch = getchar(); }
return x * f;
}
int n , k , tot , ans = inf;
signed main ()
{
ios::sync_with_stdio(false);
cin.tie(0) , cout.tie(0);
int T = read();
while ( T -- )
{
n = read() , k = read();
for ( int i = 1 ; i <= n ; i ++ )
{
if ( i % 3 == 1 ) cout << 'a';
if ( i % 3 == 2 ) cout << 'b';
if ( i % 3 == 0 ) cout << 'c';
}
cout << endl;
}
return 0;
}
Find the Spruce
很有意思的题 我们设 \(f[i][j][k]\) 为 \((i,j)\) 节点 大小为 \(k\) 的可行性
那么 \(f[i][j][k]\) 可行当且仅当它下一行的三个节点都可以做出 \(k-1\) 大小的树
那么 \(O(nmk)\) 枚举即可 其中 \(k\) 可以取 \(max(n,m)/2+1\) 不然会炸空间
最后只需要累加一下即可
#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define inl inline
#define eb emplace_back
#define mid (l+r>>1)
#define ls p<<1
#define rs p<<1|1
#define lson ls,l,mid
#define rson rs,mid+1,r
#define getchar() cin.get()
#define print(x) cout<<#x<<'='<<x<<endl
const int N = 500 + 5;
const int inf = 0x3f3f3f3f;
int read()
{
int f = 1 , x = 0;
char ch = getchar();
while ( !isdigit(ch) ) { if ( ch == '-' ) f = -1; ch = getchar(); }
while ( isdigit(ch) ) { x = ( x << 1 ) + ( x << 3 ) + ( ch ^ 48 ); ch = getchar(); }
return x * f;
}
int n , m , k , tot , f[N][N][255] , ans;
char mp[N][N];
signed main ()
{
ios::sync_with_stdio(false);
cin.tie(0) , cout.tie(0);
int T = read();
while ( T -- )
{
ans = 0;
memset ( f , 0 , sizeof f );
n = read() , m = read();
for ( int i = 1 ; i <= n ; i ++ )
for ( int j = 1 ; j <= m ; j ++ )
cin >> mp[i][j] , f[i][j][1] = ( mp[i][j] == '*' );
for ( int i = n - 1 ; i ; i -- )
for ( int j = 1 ; j <= m ; j ++ )
for ( int k = 2 ; k <= max ( n , m ) / 2 + 1 ; k ++ )
if ( f[i+1][j-1][k-1] && f[i+1][j][k-1] && f[i+1][j+1][k-1] && mp[i][j] == '*' ) f[i][j][k] = 1;
for ( int k = 1 ; k <= max ( n , m ) / 2 + 1 ; k ++ )
for ( int i = 1 ; i <= n ; i ++ )
for ( int j = 1 ; j <= m ; j ++ )
ans += f[i][j][k];
cout << ans << endl;
}
return 0;
}
Random Events
可以从后往前找到第一个 \(a[i]\neq i\) 的位置 \(pos\) 所有在 \(pos\) 后面的操作才会影响 否则不影响
只要有一个达成目标即可 那么我们算出全不选的概率再用 \(1\) 减掉
#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define inl inline
#define eb emplace_back
#define mid (l+r>>1)
#define ls p<<1
#define rs p<<1|1
#define lson ls,l,mid
#define rson rs,mid+1,r
#define getchar() cin.get()
#define print(x) cout<<#x<<'='<<x<<endl
const int N = 500 + 5;
const int inf = 0x3f3f3f3f;
int read()
{
int f = 1 , x = 0;
char ch = getchar();
while ( !isdigit(ch) ) { if ( ch == '-' ) f = -1; ch = getchar(); }
while ( isdigit(ch) ) { x = ( x << 1 ) + ( x << 3 ) + ( ch ^ 48 ); ch = getchar(); }
return x * f;
}
int n , m , k , tot , f[N][N][255] , ans , a[N];
double gl , res;
signed main ()
{
ios::sync_with_stdio(false);
cin.tie(0) , cout.tie(0);
int T = read();
while ( T -- )
{
res = 1.0;
n = read() , m = read();
int pos = 0;
for ( int i = 1 ; i <= n ; i ++ ) a[i] = read();
for ( int i = n ; i ; i -- ) if ( i != a[i] ) { pos = i; break; }
for ( int i = 1 ; i <= m ; i ++ )
{
int x = read(); cin >> gl;
if ( x >= pos ) res *= ( 1.0 - gl );
}
if ( !pos ) { cout << "1.000000" << endl; continue; }
cout << fixed << setprecision(6) << 1.0 - res << endl;
}
return 0;
}
Divide and Summarize
暴力可过 破防了
一共只会有 \(nlogn\) 个区间 那么直接暴力用 \(map\) 标记即可
要开 \(long\ long\)
#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define inl inline
#define eb emplace_back
#define mid (l+r>>1)
#define ls p<<1
#define rs p<<1|1
#define lson ls,l,mid
#define rson rs,mid+1,r
#define getchar() cin.get()
#define print(x) cout<<#x<<'='<<x<<endl
#define int long long
const int N = 1e5 + 5;
const int M = 1e6 + 5;
const int inf = 0x3f3f3f3f;
int read()
{
int f = 1 , x = 0;
char ch = getchar();
while ( !isdigit(ch) ) { if ( ch == '-' ) f = -1; ch = getchar(); }
while ( isdigit(ch) ) { x = ( x << 1 ) + ( x << 3 ) + ( ch ^ 48 ); ch = getchar(); }
return x * f;
}
int n , q , a[N] , sum[N];
map<int,int> mp;
void solve ( int l , int r )
{
mp[sum[r]-sum[l-1]] = 1;
if ( l == r ) return;
int pos = upper_bound ( a + l , a + r + 1 , ( a[l] + a[r] ) / 2 ) - a - 1;
if ( pos >= r ) return;
solve ( l , pos ) , solve ( pos + 1 , r );
}
signed main ()
{
ios::sync_with_stdio(false);
cin.tie(0) , cout.tie(0);
int T = read();
while ( T -- )
{
mp.clear();
n = read() , q = read();
for ( int i = 1 ; i <= n ; i ++ ) a[i] = read();
sort ( a + 1 , a + n + 1 );
for ( int i = 1 ; i <= n ; i ++ ) sum[i] = sum[i-1] + a[i];
solve ( 1 , n );
while ( q -- ) cout << ( mp[read()] ? "Yes" : "No" ) << endl;
}
return 0;
}
Water Level
分讨题()
我们对 \(x\) 和 \(y\) 的大小关系进行考虑
-
\(x=y\) 只要加一次水或者喝一次水在区间内就是合法的
-
\(x>y\) 那么相当于是水量一直在减少 那么用除法算一下还能喝多少天(注意特判第一次加水溢出的情况)
-
\(x<y\) 我们不担心水不够 而是担心会不会溢出 那么我们每一次都减到 \(\ge l\) 的第一个位置 并让目标天数减去这些天
如果 \(\le 0\) 那么直接输出 \(Yes\) 否则更新水量并加上 \(y\)
一个优化:我们记录 \(k \bmod x\) 的值是否被访问过 如果访问过 那么一定是可以通过一些循环来实现无限次的控制水量 输出 \(Yes\)
#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define inl inline
#define eb emplace_back
#define mid (l+r>>1)
#define ls p<<1
#define rs p<<1|1
#define lson ls,l,mid
#define rson rs,mid+1,r
#define getchar() cin.get()
#define print(x) cout<<#x<<'='<<x<<endl
#define int __int128
const int N = 1e6 + 5;
const int mod = 1e9 + 7;
int read()
{
int f = 1 , x = 0;
char ch = getchar();
while ( !isdigit(ch) ) { if ( ch == '-' ) f = -1; ch = getchar(); }
while ( isdigit(ch) ) { x = ( x << 1 ) + ( x << 3 ) + ( ch ^ 48 ); ch = getchar(); }
return x * f;
}
int k , l , r , t , x , y , vis[N];
signed main ()
{
ios::sync_with_stdio(false);
cin.tie(0) , cout.tie(0);
k = read() , l = read() , r = read() , t = read() , x = read() , y = read();
if ( x == y ) cout << ( ( l <= k - x || k + x <= r ) ? "Yes" : "No" ) << endl;
else if ( x > y )
{
int res = 0;
if ( k + y > r ) k -= x , ++ res;//溢出 不能加水
if ( k < l ) return cout << "No" << endl , 0;
res += ( k - l ) / ( x - y );
cout << ( res >= t ? "Yes" : "No" ) << endl;
}
else
{
while ( t > 0 )
{
if ( vis[k%x] ) return cout << "Yes" << endl , 0;
int rem = min ( t , ( k - l ) / x );
t -= rem;
if ( t <= 0 ) return cout << "Yes" << endl , 0;
k -= rem * x , vis[k%x] = 1 , k += y;
if ( k < l || k > r ) return cout << "No" << endl , 0;
}
}
return 0;
}
Mathematical Expression
随的一场 \(CF\) 竟然出现了模拟赛原题?
首先分讨
- 三种全有 显然减号是没用的 相当于只有加和乘 归入下面的情况中
- 只有两种
- 加和乘 这是我们讨论的重点 放在下面讨论
- 减和加 一定加就完事了
- 减和乘 一定是找到从前往后第一个 \(0\) 这个数的前面为减号 其余符号均为乘号 对于这个数在第一位的情况特判一下即可
- 只有一种 直接输出即可
下面讨论加乘的情况
\(upd:\) 看 \(1h\) 题解后放弃 真 \(tm\) 做不了 下面给出除了加乘的代码
#include<bits/stdc++.h>
using namespace std;
#define mid ((l+r)>>1)
#define inl inline
#define eb emplace_back
#define endl '\n'
#define print(x) cerr<<#x<<'='<<x<<endl
#define getchar() cin.get()
const int N = 1e5 + 5;
int read()
{
int x = 0 , f = 1;
char ch = getchar();
while ( !isdigit(ch) ) { if ( ch == '-' ) f = -1; ch = getchar(); }
while ( isdigit(ch) ) { x = ( x << 1 ) + ( x << 3 ) + ( ch ^ 48 ); ch = getchar(); }
return x * f;
}
int n , m , a[N] , vis[3] , ans , t[N];//+-*
string s , res;
namespace sub1
{
void main()
{
}
}
namespace sub2
{
void main ()
{
cout << a[1];
for ( int i = 2 ; i <= n ; i ++ )
cout << '+' << a[i];
}
}
namespace sub3
{
void main ()
{
int hav = 0;
cout << a[1];
for ( int i = 2 ; i <= n ; i ++ )
{
if ( !a[i] && !hav ) cout << '-' , hav = 1;
else cout << '*';
cout << a[i];
}
}
}
namespace sub4
{
void main ()
{
cout << a[1];
for ( int i = 2 ; i <= n ; i ++ )
{
if ( vis[0] ) cout << '+';
else if ( vis[1] ) cout << '-';
else cout << '*';
cout << a[i];
}
cout << endl;
}
}
/*
5
1 2 3 0 5
+*
*/
signed main ()
{
// freopen ( "max.in" , "r" , stdin );
// freopen ( "max.out" , "w" , stdout );
ios::sync_with_stdio(false);
cin.tie(0) , cout.tie(0);
n = read();
for ( int i = 1 ; i <= n ; i ++ ) a[i] = read();
cin >> s;
for ( int i = 0 ; i < s.size() ; i ++ )
{
if ( s[i] == '+' ) vis[0] = 1;
else if ( s[i] == '-' ) vis[1] = 1;
else vis[2] = 1;
}
int judge = vis[0] + vis[1] + vis[2];
if ( judge == 3 || vis[0] && vis[2] ) sub1::main();
else if ( vis[0] && vis[1] ) sub2::main();//+-
else if ( vis[1] && vis[2] ) sub3::main();//*-
else sub4::main();//only 1
return 0;
}