A题
首先第一步是把所有人都移动到另一侧。
然后就是等待缓冲时间,需要分类讨论,手动模拟一下即可找到规律。
最后一步就是把所有人都移动到初始侧。
#include<bits/stdc++.h>
#define pb push_back
#define fi first
#define se second
#define sz(x) (int)x.size()
#define cl(x) x.clear()
#define all(x) x.begin() , x.end()
#define rep(i , x , n) for(int i = x ; i <= n ; i ++)
#define per(i , n , x) for(int i = n ; i >= x ; i --)
#define mem0(x) memset(x , 0 , sizeof(x))
#define mem_1(x) memset(x , -1 , sizeof(x))
#define mem_inf(x) memset(x , 0x3f , sizeof(x))
#define debug(x) cerr << #x << " = " << x << '\n'
#define ddebug(x , y) cerr << #x << " = " << x << " " << #y << " = " << y << '\n'
#define ios std::ios::sync_with_stdio(false) , cin.tie(0)
using namespace std ;
typedef long long ll ;
typedef long double ld ;
typedef pair<int , int> pii ;
typedef pair<ll , ll> pll ;
typedef double db ;
const int mod = 998244353 ;
const int maxn = 2e5 + 10 ;
const int inf = 0x3f3f3f3f ;
const double eps = 1e-6 ;
int main()
{
ios ;
int T ;
cin >> T ;
while(T --)
{
ll n , x , t ;
cin >> n >> x >> t ;
ll ans = 0 ;
ans += 4 * n * t ;
if(x > 2 * (n - 1) * t)
{
ll res = 0 ;
res += 2 * n * t + t ;
if(res - t < x) res = t + x - (res - t) ;
else res = t ;
ans += min(res , x - 2 * (n - 1) * t) ;
}
cout << ans << '\n' ;
}
return 0 ;
}
C题
参考dalao
想到公式后,很裸的换根dp。
#include<bits/stdc++.h>
#define pb push_back
#define fi first
#define se second
#define sz(x) (int)x.size()
#define cl(x) x.clear()
#define all(x) x.begin() , x.end()
#define rep(i , x , n) for(int i = x ; i <= n ; i ++)
#define per(i , n , x) for(int i = n ; i >= x ; i --)
#define mem0(x) memset(x , 0 , sizeof(x))
#define mem_1(x) memset(x , -1 , sizeof(x))
#define mem_inf(x) memset(x , 0x3f , sizeof(x))
#define debug(x) cerr << #x << " = " << x << '\n'
#define ddebug(x , y) cerr << #x << " = " << x << " " << #y << " = " << y << '\n'
#define ios std::ios::sync_with_stdio(false) , cin.tie(0)
using namespace std ;
typedef long long ll ;
typedef long double ld ;
typedef pair<int , int> pii ;
typedef pair<ll , ll> pll ;
typedef double db ;
const int mod = 998244353 ;
const int maxn = 2e5 + 10 ;
const int inf = 0x3f3f3f3f ;
const double eps = 1e-6 ;
int n ;
vector<pii> g[maxn] ;
bool vis[maxn] ;
ll dp[maxn][3] ;
int cnt[maxn] ;
int siz[5] ;
vector<int> c[3] ;
void dfs1(int fa , int u , int id)
{
cnt[u] += vis[u] ;
for(auto x : g[u])
{
int v = x.fi ;
int w = x.se ;
if(v == fa) continue ;
dfs1(u , v , id) ;
cnt[u] += cnt[v] ;
dp[u][id] += dp[v][id] + 1ll * cnt[v] * w ;
//if(u == 1 && id == 2) ddebug(dp[v][id] , 1ll * cnt[v] * w) ;
}
}
void dfs2(int fa , int u , int id)
{
for(auto x : g[u])
{
int v = x.fi ;
int w = x.se ;
if(v == fa) continue ;
dp[v][id] += (dp[u][id] - dp[v][id] - 1ll * cnt[v] * w) + 1ll * (cnt[1] - cnt[v]) * w ;
dfs2(u , v , id) ;
}
}
int main()
{
ios ;
cin >> n ;
rep(i , 1 , n - 1)
{
int u , v , w ;
cin >> u >> v >> w ;
g[u].pb({v , w}) ;
g[v].pb({u , w}) ;
}
rep(i , 0 , 2)
{
int k ;
cin >> k ;
siz[i] = k ;
mem0(vis) ;
mem0(cnt) ;
rep(j , 1 , k)
{
int x ;
cin >> x ;
vis[x] = 1 ;
c[i].pb(x) ;
}
dfs1(1 , 1 , i) ;
dfs2(1 , 1 , i) ;
}
db ans = 0 ;
for(auto x : c[0]) ans += dp[x][1] * siz[2] ;
for(auto x : c[0]) ans += dp[x][2] * siz[1] ;
for(auto x : c[1]) ans += dp[x][2] * siz[0] ;
ans /= 2 ;
ans /= siz[0] ;
ans /= siz[1] ;
ans /= siz[2] ;
cout << fixed << setprecision(15) << ans << '\n' ;
return 0 ;
}
D题
不是很会证明,打个表规律全出来了。
把c质因数分解,如果每个质数的指数都是1,那就输出no。
然后考虑怎么判断c可以整除某个质数的平方。
数据范围写着时间复杂度是。手推一下就可以判断了。
#include<bits/stdc++.h>
#define pb push_back
#define fi first
#define se second
#define sz(x) (int)x.size()
#define cl(x) x.clear()
#define all(x) x.begin() , x.end()
#define rep(i , x , n) for(int i = x ; i <= n ; i ++)
#define per(i , n , x) for(int i = n ; i >= x ; i --)
#define mem0(x) memset(x , 0 , sizeof(x))
#define mem_1(x) memset(x , -1 , sizeof(x))
#define mem_inf(x) memset(x , 0x3f , sizeof(x))
#define debug(x) cerr << #x << " = " << x << '\n'
#define ddebug(x , y) cerr << #x << " = " << x << " " << #y << " = " << y << '\n'
#define ios std::ios::sync_with_stdio(false) , cin.tie(0)
using namespace std ;
typedef long long ll ;
typedef long double ld ;
typedef pair<int , int> pii ;
typedef pair<ll , ll> pll ;
typedef double db ;
const int mod = 998244353 ;
const int maxn = 2e5 + 10 ;
const int inf = 0x3f3f3f3f ;
const double eps = 1e-6 ;
struct Easymath
{
ll qpow(ll a , ll b) //快速幂
{
if(b < 0) return 0 ;
ll ans = 1 ;
a %= mod ;
while(b)
{
if(b & 1) ans = (ans * a) % mod ;
b >>= 1 , a = (a * a) % mod ;
}
return ans % mod ;
}
ll ksc_log(ll x , ll y , ll mod) //快速乘
{
x %= mod , y %= mod ;
ll ans = 0;
while(y)
{
if(y & 1) ans = (ans + x) % mod ;
y >>= 1 ;
x = (x + x) % mod ;
}
return ans;
}
ll ksc_O1(ll x , ll y , ll mod) //快速乘
{
x %= mod , y %= mod ;
ll z = (ld)x * y / mod ;
ll ans = x * y - z * mod ;
if(ans < 0) ans += mod ;
else if(ans >= mod) ans -= mod ;
return ans ;
}
int cnt = 0 ;
bool vis[maxn] ;
int prime[maxn] ;
void get_prime(int up) //素数筛
{
memset(vis , 0 , sizeof(vis)) ;
vis[1] = 1 ;
for(int i = 2 ; i <= up ; i ++)
{
if(!vis[i])
prime[++ cnt] = i ;
for(int j = 1 ; j <= cnt && i * prime[j] <= up ; j ++)
{
vis[i * prime[j]] = 1 ;
if(i % prime[j] == 0) break ;
}
}
}
//begin 判定大素数
ll mul(ll a , ll b , ll mod)
{
ll ret = 0 ;
while(b)
{
if(b & 1) ret = (ret + a) % mod ;
a = (a + a) % mod ;
b >>= 1 ;
}
return ret ;
}
ll pow(ll a , ll b , ll mod)
{
ll ret = 1 ;
while(b)
{
if(b & 1) ret = mul(ret , a , mod) ;
a = mul(a , a , mod) ;
b >>= 1 ;
}
return ret ;
}
bool check(ll a , ll n)
{
ll x = n - 1 ;
int t = 0 ;
while((x & 1) == 0)
{
x >>= 1 ;
t ++ ;
}
x = pow(a , x , n) ;
ll y ;
rep(i , 1 , t)
{
y = mul(x , x , n) ;
if(y == 1 && x != 1 && x != n - 1) return 1 ;
x = y ;
}
if(y != 1) return 1 ;
return 0 ;
}
bool Miller_Rabin(ll n)
{
if(n == 2) return 1 ;
if(n == 1 || !(n & 1)) return 0 ;
const int arr[12] = {2,3,5,7,11,13,17,19,23,29,31,37} ;
rep(i , 0 , 11)
{
if(arr[i] >= n) break ;
if(check(arr[i] , n)) return 0 ;
}
return 1 ;
}
//end 判定大素数
ll get_inv(ll x) //逆元
{
return qpow(x , mod - 2) % mod ;
}
ll inv1[maxn] ; //乘法逆元
void init1(int up)
{
inv1[1] = 1 ;
for(int i = 2 ; i <= up ; i ++)
inv1[i] = (ll)(mod - mod / i) * inv1[int(mod % (ll)i)] % mod ;
}
ll fac[maxn] ;
ll inv[maxn] ; //阶乘逆元
void init(int up)
{
fac[0] = fac[1] = inv[0] = inv[1] = 1 ;
for(int i = 2 ; i <= up ; i ++)
{
fac[i] = fac[i - 1] * i % mod ;
inv[i] = -inv[mod % i] * (mod / i) % mod ;
while(inv[i] < 0) inv[i] += mod ;
}
for(int i = 2 ; i <= up ; i ++)
inv[i] = inv[i] * inv[i - 1] % mod ;
}
ll C(int n , int m)
{
return fac[n] * inv[m] % mod * inv[n - m] % mod ;
}
} em ;
void win()
{
cout << "yes\n" ;
}
void lose()
{
cout << "no\n" ;
}
int rad(int x)
{
int res = 1 ;
rep(i , 2 , x) if(!em.vis[i] && x % i == 0) res *= i ;
return res ;
}
bool ok(int i)
{
rep(j , 1 , i - 1) if(rad(j * (i - j) * i) < i) return 1 ;
return 0 ;
}
void solve()
{
ll n ;
bool flag = 0 ;
cin >> n ;
rep(i , 2 , 1000000)
{
ll tmp = 1ll * i * i * i ;
if(tmp > n) break ;
else if(n % tmp == 0)
{
flag = 1 ;
break ;
}
}
rep(i , 2 , 1000000)
{
ll tmp = 1ll * i * i ;
if(tmp > n) break ;
else if(n % tmp == 0)
{
flag = 1 ;
break ;
}
}
rep(i , 2 , 1000000)
{
if(i > n) break ;
while(n % i == 0) n /= i ;
}
if(flag == 0 && n > 1)
{
ll tmp = sqrt(n + 0.5) ;
if(tmp * tmp == n) flag = 1 ;
}
if(flag) win() ;
else lose() ;
}
int main()
{
ios ;
int T ;
cin >> T ;
while(T --) solve() ;
return 0 ;
}
G题
首先判断两个区间是否相同基本就是hash了。
区间加那就是线段树。
所以这题就是线段树hash。
因为有个取模操作,但是因为每次区间加1,所以每个数取模次数均摊下来不会很多,大约每个数取模10次。
可以树上二分,暴力点修改取模。记录个区间最大值就好了。
#include<bits/stdc++.h>
#define pb push_back
#define fi first
#define se second
#define sz(x) (int)x.size()
#define cl(x) x.clear()
#define all(x) x.begin() , x.end()
#define rep(i , x , n) for(int i = x ; i <= n ; i ++)
#define per(i , n , x) for(int i = n ; i >= x ; i --)
#define mem0(x) memset(x , 0 , sizeof(x))
#define mem_1(x) memset(x , -1 , sizeof(x))
#define mem_inf(x) memset(x , 0x3f , sizeof(x))
#define debug(x) cerr << #x << " = " << x << '\n'
#define ddebug(x , y) cerr << #x << " = " << x << " " << #y << " = " << y << '\n'
#define ios std::ios::sync_with_stdio(false) , cin.tie(0)
using namespace std ;
typedef long long ll ;
typedef long double ld ;
typedef pair<int , int> pii ;
typedef pair<ll , ll> pll ;
typedef double db ;
const int maxn = 5e5 + 10 ;
const int inf = 0x3f3f3f3f ;
const double eps = 1e-6 ;
typedef unsigned long long ull ;
const ull mod = 21788233 ;
ull base = 131 ;
int a[maxn] ;
ull p[maxn] ;
ull pre[maxn] ;
struct seg_tree
{
ull mx[maxn << 2] , add[maxn << 2] ;
ull hash1[maxn << 2] ;
int ls(int x)
{
return x << 1 ;
}
int rs(int x)
{
return x << 1 | 1 ;
}
void push_up(int id , int len)
{
mx[id] = max(mx[ls(id)] , mx[rs(id)]) ;
hash1[id] = hash1[ls(id)] * p[len] + hash1[rs(id)] ;
hash1[id] %= mod ;
}
void build(int id , int l , int r)
{
add[id] = 0 ;
if(l == r)
{
mx[id] = hash1[id] = a[l] ;
return ;
}
int mid = (l + r) >> 1 ;
build(ls(id) , l , mid) ;
build(rs(id) , mid + 1 , r) ;
push_up(id , r - mid) ;
}
void f(int id , int l , int r , ll k)
{
add[id] = add[id] + k , add[id] %= mod;
mx[id] = mx[id] + k , mx[id] %= mod;
hash1[id] = hash1[id] + k * pre[r - l] ;
hash1[id] %= mod ;
}
void push_down(int id , int l , int r)
{
int mid = (l + r) >> 1 ;
f(ls(id) , l , mid , add[id]) ;
f(rs(id) , mid + 1 , r , add[id]) ;
add[id] = 0 ;
}
void update(int id , int l , int r , int x , int y , ll k)
{
if(x > y || x > r || y < l) return ; //±ÜÃâÔ½½ç¡£
if(x <= l && r <= y)
{
mx[id] += k ;
add[id] += k ;
hash1[id] += pre[r - l] ;
hash1[id] %= mod;
return ;
}
push_down (id , l , r) ;
int mid = (l + r) >> 1 ;
if(x <= mid) update(ls(id) , l , mid , x , y , k) ;
if(y > mid) update(rs(id) , mid + 1 , r , x , y , k) ;
push_up(id , r - mid) ;
}
ull query(int id , int l , int r , int x , int y)
{
if(x > y || x > r || y < l) return 0 ; //±ÜÃâÔ½½ç¡£
ull ans = 0 ;
if(x <= l && r <= y) return hash1[id] ;
int mid = (l + r) >> 1 ;
push_down(id , l , r) ;
if(y <= mid) return query(ls(id) , l , mid , x , y) ;
else if(mid + 1 <= x) return query(rs(id) , mid + 1 , r , x , y) ;
else
{
ans += query(ls(id) , l , mid , x , y) * p[min(r , y) - mid] ;
ans += query(rs(id) , mid + 1 , r , x , y) ;
return ans % mod ;
}
}
void dfs(int id , int l , int r)
{
int mid = (l + r) >> 1 ;
if(mx[id] < 65536) return ;
if(l == r)
{
hash1[id] = 0 ;
mx[id] = 0 ;
return ;
}
push_down(id , l , r) ;
if(mx[ls(id)] == 65536) dfs(ls(id) , l , mid) ;
if(mx[rs(id)] == 65536) dfs(rs(id) , mid + 1 , r) ;
push_up(id , r - mid) ;
}
} seg ;
int main()
{
ios ;
int n , q ;
cin >> n >> q ;
rep(i , 1 , n) cin >> a[i] ;
p[0] = 1 ;
pre[0] = 1 ;
for(int i = 1 ; i <= n ; i ++) p[i] = p[i - 1] * 131 , p[i] %= mod ;
for(int i = 1 ; i <= n ; i ++) pre[i] = pre[i - 1] + p[i] , pre[i] %= mod ;
seg.build(1 , 1 , n) ;
while(q --)
{
int op ;
cin >> op ;
if(op == 1)
{
int l , r ;
cin >> l >> r ;
seg.update(1 , 1 , n , l , r , 1) ;
seg.dfs(1 , 1 , n) ;
}
else
{
int x , y , L ;
cin >> x >> y >> L ;
ull h1 = seg.query(1 , 1 , n , x , x + L - 1) ;
ull h2 = seg.query(1 , 1 , n , y , y + L - 1) ;
if(h1 == h2) cout << "yes\n" ;
else cout << "no\n" ;
}
}
return 0 ;
}
H题
直接模拟就行了。
#include<bits/stdc++.h>
#define pb push_back
#define fi first
#define se second
#define sz(x) (int)x.size()
#define cl(x) x.clear()
#define all(x) x.begin() , x.end()
#define rep(i , x , n) for(int i = x ; i <= n ; i ++)
#define per(i , n , x) for(int i = n ; i >= x ; i --)
#define mem0(x) memset(x , 0 , sizeof(x))
#define mem_1(x) memset(x , -1 , sizeof(x))
#define mem_inf(x) memset(x , 0x3f , sizeof(x))
#define debug(x) cerr << #x << " = " << x << '\n'
#define ddebug(x , y) cerr << #x << " = " << x << " " << #y << " = " << y << '\n'
#define ios std::ios::sync_with_stdio(false) , cin.tie(0)
using namespace std ;
typedef long long ll ;
typedef long double ld ;
typedef pair<int , int> pii ;
typedef pair<ll , ll> pll ;
typedef double db ;
const int mod = 998244353 ;
const int maxn = 2e5 + 10 ;
const int inf = 0x3f3f3f3f ;
const double eps = 1e-6 ;
int n , m , s ;
map<int , int> a[maxn] ;
int b[maxn] ;
int ans[maxn] ;
int main()
{
ios ;
cin >> m >> n >> s ;
while(s --)
{
int t , x , y ;
cin >> t >> x >> y ;
if(t == 1) a[x][y] = b[y] ;
else if(t == 2)
{
ans[x] += b[y] - a[x][y] ;
a[x].erase(y) ;
}
else ans[x] -- , b[y] ++ ;
}
rep(i , 1 , n) for(auto x : a[i]) ans[i] += b[x.fi] - x.se ;
rep(i , 1 , n) cout << ans[i] << '\n' ;
return 0 ;
}
L题
构造一个任意长度的序列,。
最大化序列的lcm。
每个质数的幂次认为是一组,跑分组背包。
#include<bits/stdc++.h>
#define pb push_back
#define fi first
#define se second
#define sz(x) (int)x.size()
#define cl(x) x.clear()
#define all(x) x.begin() , x.end()
#define rep(i , x , n) for(int i = x ; i <= n ; i ++)
#define per(i , n , x) for(int i = n ; i >= x ; i --)
#define mem0(x) memset(x , 0 , sizeof(x))
#define mem_1(x) memset(x , -1 , sizeof(x))
#define mem_inf(x) memset(x , 0x3f , sizeof(x))
#define debug(x) cerr << #x << " = " << x << '\n'
#define ddebug(x , y) cerr << #x << " = " << x << " " << #y << " = " << y << '\n'
#define ios std::ios::sync_with_stdio(false) , cin.tie(0)
using namespace std ;
typedef long long ll ;
typedef long double ld ;
typedef pair<int , int> pii ;
typedef pair<ll , ll> pll ;
typedef double db ;
const int mod = 998244353 ;
const int maxn = 2e5 + 10 ;
const int inf = 0x3f3f3f3f ;
const double eps = 1e-6 ;
db lg[maxn] ;
db dp[maxn] ;
struct Easymath
{
ll qpow(ll a , ll b) //快速幂
{
if(b < 0) return 0 ;
ll ans = 1 ;
a %= mod ;
while(b)
{
if(b & 1) ans = (ans * a) % mod ;
b >>= 1 , a = (a * a) % mod ;
}
return ans % mod ;
}
ll ksc_log(ll x , ll y , ll mod) //快速乘
{
x %= mod , y %= mod ;
ll ans = 0;
while(y)
{
if(y & 1) ans = (ans + x) % mod ;
y >>= 1 ;
x = (x + x) % mod ;
}
return ans;
}
ll ksc_O1(ll x , ll y , ll mod) //快速乘
{
x %= mod , y %= mod ;
ll z = (ld)x * y / mod ;
ll ans = x * y - z * mod ;
if(ans < 0) ans += mod ;
else if(ans >= mod) ans -= mod ;
return ans ;
}
int cnt = 0 ;
bool vis[maxn] ;
int prime[maxn] ;
void get_prime(int up) //素数筛
{
memset(vis , 0 , sizeof(vis)) ;
vis[1] = 1 ;
for(int i = 2 ; i <= up ; i ++)
{
if(!vis[i])
prime[++ cnt] = i ;
for(int j = 1 ; j <= cnt && i * prime[j] <= up ; j ++)
{
vis[i * prime[j]] = 1 ;
if(i % prime[j] == 0) break ;
}
}
}
//begin 判定大素数
ll mul(ll a , ll b , ll mod)
{
ll ret = 0 ;
while(b)
{
if(b & 1) ret = (ret + a) % mod ;
a = (a + a) % mod ;
b >>= 1 ;
}
return ret ;
}
ll pow(ll a , ll b , ll mod)
{
ll ret = 1 ;
while(b)
{
if(b & 1) ret = mul(ret , a , mod) ;
a = mul(a , a , mod) ;
b >>= 1 ;
}
return ret ;
}
bool check(ll a , ll n)
{
ll x = n - 1 ;
int t = 0 ;
while((x & 1) == 0)
{
x >>= 1 ;
t ++ ;
}
x = pow(a , x , n) ;
ll y ;
rep(i , 1 , t)
{
y = mul(x , x , n) ;
if(y == 1 && x != 1 && x != n - 1) return 1 ;
x = y ;
}
if(y != 1) return 1 ;
return 0 ;
}
bool Miller_Rabin(ll n)
{
if(n == 2) return 1 ;
if(n == 1 || !(n & 1)) return 0 ;
const int arr[12] = {2,3,5,7,11,13,17,19,23,29,31,37} ;
rep(i , 0 , 11)
{
if(arr[i] >= n) break ;
if(check(arr[i] , n)) return 0 ;
}
return 1 ;
}
//end 判定大素数
ll get_inv(ll x) //逆元
{
return qpow(x , mod - 2) % mod ;
}
ll inv1[maxn] ; //乘法逆元
void init1(int up)
{
inv1[1] = 1 ;
for(int i = 2 ; i <= up ; i ++)
inv1[i] = (ll)(mod - mod / i) * inv1[int(mod % (ll)i)] % mod ;
}
ll fac[maxn] ;
ll inv[maxn] ; //阶乘逆元
void init(int up)
{
fac[0] = fac[1] = inv[0] = inv[1] = 1 ;
for(int i = 2 ; i <= up ; i ++)
{
fac[i] = fac[i - 1] * i % mod ;
inv[i] = -inv[mod % i] * (mod / i) % mod ;
while(inv[i] < 0) inv[i] += mod ;
}
for(int i = 2 ; i <= up ; i ++)
inv[i] = inv[i] * inv[i - 1] % mod ;
}
ll C(int n , int m)
{
return fac[n] * inv[m] % mod * inv[n - m] % mod ;
}
void init()
{
vector<int> v[3300 + 10] ;
get_prime(30000) ;
int num = 0 ;
rep(i , 1 , cnt)
{
int x = prime[i] ;
for(int j = x ; j <= 30000 ; j *= x) v[i].pb(j) , num ++ ;
}
rep(i , 1 , 30000) lg[i] = log(i) ;
rep(i , 1 , cnt) per(j , 30000 , 1) for(auto x : v[i]) if(j >= x) dp[j] = max(dp[j] , dp[j - x] + lg[x]) ;
rep(i , 1 , 30000) dp[i] = max(dp[i] , dp[i - 1]) ;
}
} em ;
int main()
{
ios ;
cout << fixed << setprecision(15) ;
em.init() ;
int T ;
cin >> T ;
while(T --)
{
int n ;
cin >> n ;
cout << dp[n] << '\n' ;
}
return 0 ;
}