目录
G - Genshin Impact Startup Forbidden II
H - Genshin Impact Startup Forbidden III
J - Points on the Number Axis A
A - Long Live
题目是英文的,实际上就是要a*b最大,明显的a等于1的时候这两个数最大,也就是,答案就是
1 和 根号里面的数
LL lcm(LL a,LL b){
return a/__gcd(a,b)*b;
}
void solve(){
LL x,y; cin>>x>>y;
int xy = __gcd(x,y);
LL ans = (LL)x/xy*y/xy;
cout << 1 << ' ' << ans << endl;
return ;
}
B - Nana Likes Polygons
选择三个点构成的面积最小,可以发现数据范围很小直接暴力即可,注意三点共线是无解设置都报了 eps即可
void solve(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>x[i]>>y[i];
}
auto get = [&](double x1,double y1,double x2,double y2,double x3,double y3){
return 1.0/2.0*(x1*y2+x2*y3+x3*y1-x1*y3-x2*y1-x3*y2);
};
double ans = 4e18;
for(int i=1;i<=n;i++)
for(int j=i+1;j<=n;j++)
for(int k=j+1;k<=n;k++){
double t = get(x[i],y[i],x[j],y[j],x[k],y[k]);
t = fabs(t);
if(t<esp) continue;
ans = min(ans,t);
}
if(ans==4e18) return cout << -1 << endl,void();
cout << LF(10) << ans << endl;
return ;
}
E - Spicy or Grilled?
直接按照题目来即可
void solve(){
LL n,x,a,b;
cin>>n>>x>>a>>b;
cout<<a*(n-x)+b*x<<endl;
}
F - Enchanted
逐步的拆解可以发现题目虽然很复杂,但是操作按照题目意思来获取即可
发现值域很小可以直接用二进制来表示,这样的话对于区间的合并最大次其实就是整个和的最大二进制位即可,其他操作也是对二进制位的维护,对于修改以及返回历史版本就需要使用主席树来维护即可
LL w[N],rt[N];
int idx;
int rnd(){
A = (LL)(7*A+13)%mod1;
return A;
}
struct code{
int l,r; LL v;
}tr[N*32];
void pushup(int p){
tr[p].v = tr[tr[p].l].v + tr[tr[p].r].v;
}
int build(int l,int r){
int p = ++idx;
if(l==r){
tr[p].v = w[l];
return p;
}
int mid=l+r>>1;
tr[p].l=build(l,mid);
tr[p].r=build(mid+1,r);
pushup(p);
return p;
}
int insert(int last,int l,int r,int pos,int v){
int now=++idx;
tr[now]=tr[last];
if(l==r){
tr[now].v=v;
return now;
}
int mid=l+r>>1;
if(pos<=mid) tr[now].l=insert(tr[now].l,l,mid,pos,v);
else tr[now].r=insert(tr[now].r,mid+1,r,pos,v);
pushup(now);
return now;
}
LL query(int now,int l,int r,int L,int R){
if(L <= l and r <= R) return tr[now].v;
int mid = l+r>>1;
LL res = 0;
if(L<=mid) res+=query(tr[now].l,l,mid,L,R);
if(R>mid) res+=query(tr[now].r,mid+1,r,L,R);
return res;
}
void solve(){
cin>>n>>m>>A>>p>>q;
for(int i=1;i<=n;i++){
w[i] = rnd()%q+1;
w[i]=1ll<<w[i];
}
rt[0]=build(1,n);
for(int i=1;i<=m;i++){
rt[i]=rt[i-1];
int op = rnd()%p+1;
if(op==1){
int l=rnd()%n+1,r=rnd()%n+1;
if(l>r) swap(l,r);
LL ans = query(rt[i],1,n,l,r);
cout <<__lg(ans) << endl;
}
else if(op==2){
int l=rnd()%n+1,r=rnd()%n+1;
if(l>r) swap(l,r);
int k=rnd()%q+1;
LL c = query(rt[i],1,n,l,r);
LL ans = 0;
for(int j=0;c;j++){
if(j>=k){
if(c&1){
ans += (1ll<<(j+1)) % mod;
ans %= mod;
}
else break;
}
c>>=1;
}
cout << ans << endl;
}
else if(op==3){
int pos = rnd()%n+1;
LL k = rnd()%q+1;
k = 1ll<<k;
rt[i] = insert(rt[i-1],1,n,pos,k);
}
else{
int nt = rnd()%i;
rt[i] = rt[nt];
}
}
return ;
}
G - Genshin Impact Startup Forbidden II
题目很长其实就是介绍了围棋规则,我们发现时间给了4s中我们可以对于下了每一步棋之后对包括周围这个棋子周围的五个位置的联通块处理即可,依据题目意思我们首先要对当前颜色的对立色处理,再自己,所以直接模拟即可
int s[21][21];
int ans[3];
int dx[]={0,0,1,-1},dy[]={1,-1,0,0};
bool st[21][21];
void solve(){
n = 19;
auto bfs = [&](int x,int y){
int c = s[x][y];
queue<PII> q; q.push({x,y}); st[x][y]=true;
bool ok = false; vector<PII> v;
while(!q.empty()){
auto [x,y]=q.front(); q.pop();
v.push_back({x,y});
for(int i=0;i<4;i++){
int a=x+dx[i],b=y+dy[i];
if(a<1 or a>n or b<1 or b>n) continue;//表示越界
if(s[a][b]==-1) ok = true;
if(s[a][b]!=c or st[a][b]) continue; // 表示不是同一个颜色 或者 被使用过了
q.push({a,b});
st[a][b]=true;
}
}
if(!ok){
for(auto&[x,y]:v){
s[x][y]=-1;
ans[c]++;
}
}
};
auto get = [&](int op,vector<PII>&t){
memset(st,0,sizeof st);
for(auto&[x,y]:t){
if(x<1 or x>n or y<1 or y>n) continue;
if(st[x][y]) continue;
if(s[x][y]!=op) continue;
bfs(x,y);
}
for(auto&[x,y]:t){
if(x<1 or x>n or y<1 or y>n) continue;
if(st[x][y]) continue;
if(s[x][y]!=1^op) continue;
bfs(x,y);
}
};
memset(s,-1,sizeof s);
cin>>m;
for(int i=1;i<=m;i++){
int x,y; cin>>x>>y;
int op = i%2;
s[x][y] = op;
ans[1]=ans[0]=0;
vector<PII> t;
for(int i=0;i<4;i++) t.push_back({x+dx[i],y+dy[i]});
t.push_back({x,y});
get(op^1,t);
cout << ans[1] << ' ' << ans[0] << endl;
}
return ;
}
H - Genshin Impact Startup Forbidden III
逻辑推理,我们可以发现对于整个棋盘影响作用有效果的其实就是10个点左右,因为轰炸的范围是5个格子当两个点交叉的时候会产生两个最优的位置,10个点的话最多也就是10个,如果是只能影响到一个放鱼位置的话直接处理即可,对于其他点可以直接暴力维护时间复杂度就是,可以通过
int ans,add=100000;
int dx[]={0,0,0,1,-1},dy[]={0,1,-1,0,0};
void dfs(int u,int sum){
if(sum>add) return ;
if(u==B.size()){
for(auto&[x,y]:tv){
if(w[x][y]<s[x][y]) return ;
}
add = min(sum,add);
return ;
}
for(int i=0;i<=3;i++){
auto [x,y]=B[u];
for(int j=0;j<5;j++){
int a=x+dx[j],b=y+dy[j];
w[a][b]+=i;
}
dfs(u+1,sum+i);
for(int j=0;j<5;j++){
int a=x+dx[j],b=y+dy[j];
w[a][b]-=i;
}
}
}
void solve(){
cin>>n>>m>>k;
for(int i=1;i<=k;i++){
int x,y,c; cin>>x>>y>>c;
s[x][y]+=c;
v.push_back({x,y});
}
sort(v.begin(),v.end());
v.erase(unique(v.begin(),v.end()),v.end());
for(auto&[x,y]:v){
for(int i=0;i<5;i++){ // 跑周围的五个点算贡献
int a=x+dx[i],b=y+dy[i];
if(a<1 or a>n or b<1 or b>m) continue;
int cnt = 0;
for(int j=0;j<5;j++){
int na=a+dx[j],nb=b+dy[j];
if(na<1 or na>n or nb<1 or nb>m) continue;
if(s[na][nb]) cnt++;
}
A.push_back({cnt,a,b});
}
}
sort(A.begin(),A.end(),greater<TUP>());
A.erase(unique(A.begin(),A.end()),A.end());
for(auto[c,x,y]:A){
if(c>1){
B.push_back({x,y});
for(int i=0;i<5;i++){
int a=x+dx[i],b=y+dy[i];
if(a<1 or a>n or b<1 or b>m) continue;
if(s[a][b]) st[a][b]=true;
}
}
}
for(auto&[x,y]:v){
if(!st[x][y]) ans += s[x][y]; // 孤立的点自我检查
else tv.push_back({x,y});// 否则就是暴力检查的点
}
dfs(0,0);
ans += add;
cout << ans << endl;
}
J - Points on the Number Axis A
可以简单猜测,每个点都是随机的选取所以最后答案就是平均数
LL qmi(LL a,LL b,LL p){
LL res=1;
while(b){
if(b&1) res=res*a%p;
b>>=1;
a=a*a%p;
}
return res;
}
void solve(){
cin>>n;
int ans = 0;
for(int i=1;i<=n;i++){
int x; cin>>x;
ans += x;
ans %= mod;
}
ans = ans * qmi(n,mod-2,mod)%mod;
cout << ans << endl;
return ;
}
L - LCMs
同时考虑到是多组输入我们可以得到每次的操作次数一定是不多的,通过简单的枚举和推理可以得中间最多五个数左右,我们可以直接使用两个数的约数也是可以的,同时加上2来处理
int lcm(int a,int b){
return a/__gcd(a,b)*b;
}
void solve(){
int a,b; cin>>a>>b;
if(a==b){
cout << 0 << endl;
return ;
}
vector<int> A,B;
A.push_back(2),B.push_back(2);
A.push_back(a),B.push_back(b);
for(int i=2;i<=a/i;i++){
if(a%i==0){
int x=i,y=a/i;
if(x!=1) A.push_back(x);
if(y!=1) A.push_back(y);
}
}
for(int i=2;i<=b/i;i++){
if(b%i==0){
int x=i,y=b/i;
if(x!=1) B.push_back(x);
if(y!=1) B.push_back(y);
}
}
int ans = lcm(a,b);
for(auto&v1:A){
int now = lcm(a,v1) + lcm(b,v1);
ans = min(ans,now);
for(auto&v2:B){
int now1 = lcm(a,v1) + lcm(v1,v2) + lcm(v2,b);
int now2 = lcm(a,v1) + lcm(v1,2) + lcm(v2,2) + lcm(v2,b);
ans = min({ans,now1,now2});
}
}
for(auto&v1:B){
int now = lcm(a,v1) + lcm(b,v1);
ans = min(ans,now);
for(auto&v2:A){
int now1 = lcm(a,v1) + lcm(v1,v2) + lcm(v2,b);
int now2 = lcm(a,v1) + lcm(v1,2) + lcm(v2,2) + lcm(v2,b);
ans = min({ans,now1,now2});
}
}
cout << ans << endl;
return ;
}