杭电春季联赛 1

感觉思路大差不差,但是在代码实现方面还是有待提高
其实需要去多想一想一些小细节,不然就会很容易漏下一些东西
然后以及每天必要的代码时间也是不可少的
之后接下来一段时间应该是在练习一些写代码以及边分析边简化的能力

E

傻逼签到题,for 循环枚举应该都能过

F

傻逼贪心,按照可吃时间从小到大排序随便吃

H

考虑描述 \(a_i=k_ig,a_j=k_jg,k_i,k_j\) 互质

完全可以让 \(k_i\)\(k_j\) 很大来避免没有必要的构造

所以每次留下这些 \(g\)\(g\) 取最小公倍数,剩下的不用管

询问取这些最小公倍数的最大公约数即可

注意到 \(g\leq 30\) 维护一下指数还是相当随便做的。

G

树形 DP

除开维护所求的 \(f_x\) 还可以顺手求出留下的沙子 \(g_x\)

每次一上来先把所有的 \(g_y,y\in \text{son}_x\) 加到 \(a_x\)

如果此时 \(a_x>\min(f_y),y\in \text{son}_x\)

那么显然 \(f_x=\min(f_y),y\in \text{son}_x\) 多加的沙子没有用

否则就需要子树尽全力往上再抽沙子

注意到任意一个子树都有 \(f_y>a_x\) 所以每个点都可以往上抽沙子补齐

最终会把沙子填到每个点均等的形态,剩下的往上补。

此时,我们会发现最后仍然满足任意一个子树都有 \(f_y>=a_x\)

可以反推出满足这个就一定有任意一个子树都有 \(f_y>a_x\) 转移

所以其实直接拿后者代替就可以,不需要维护 \(g_x\)

B

首先判一下无解,\(n+1\) 个前缀和根据模 \(k\) 的余数放进 \(k\) 个桶

鸽巢原理,当且仅当 \(n<k\) 有解,此时贪心取数就可以

感觉我赛时的做法非常sb

I

随机化大显身手

可以发现其实过大的状态一定拉不回来

大胆舍弃即可

A

先分析一下博弈过程,发现是巴什博弈

结论是先手必胜当且仅当石子数模取数范围加一的余数不为零

然后就可以对式子变形了

发现 \(k\) 的次幂模意义下其实是 \(-1\) 的次幂

考虑等于零的情况,对 \(-1\) 的次数进行讨论

会发现如果奇数且等于零会推出两数相等,进而次数为偶数,不用管这里

然后就是负数的次幂为偶次,这个时候要 \(a_i+a_j=k+1\)

考虑固定 \(k\) 进行分治,每次处理跨过 \(k\) 的区间长度

会发现这个过程其实就是上了笛卡尔树

这个处理的过程用树上启发式合并即可

写的很丑的启发式合并
#include <bits/stdc++.h>
using namespace std;
#define int long long 
const int o=2222222;
int a[o],ls[o],rs[o],stk[o],top,n,ans,cnt;
unordered_map<int,int>q[o];
int read(){
    int i=1,j=0;
    char ch=getchar();
    while(ch>'9'||ch<'0'){
        if(ch=='-')i=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9'){
        j=j*10+ch-48;
        ch=getchar();
    }
    return i*j;
}
void build(){
    for (int i = 1; i <= n; i++) {
        int k=top;  
        while(k>0&&a[stk[k]]<a[i])k--;  
        if(k)rs[stk[k]]=i;  
        if(k<top)ls[i]=stk[k + 1];  
        stk[++k]=i;
        top = k;
    }
}
void in(){
    n=read();
    for(int i=1;i<=n;i++)a[i]=read();
}
int dfs(int x){
    cnt++;
    int lx=0,rx=0;
    if(ls[x])lx=dfs(ls[x]);
    if(rs[x])rx=dfs(rs[x]);
    if(ls[x]==0&&rs[x]==0){
        q[x][a[x]]++;
        if(a[x]==1)ans++;
        return x;
    }
    if(q[lx].size()>q[rx].size())swap(lx,rx);
    q[rx][a[x]]++;
    for(auto i:q[lx]){
        int now=i.first,val=i.second;
        if(a[x]&1)ans+=2*q[rx][a[x]-now+1]*val;
    }
    for(auto i:q[lx]){
        int now=i.first,val=i.second;
        q[rx][now]+=val;
    }
    ans+=(a[x]==1);
    return rx;
}
void work(){
    build();
    dfs(stk[1]);
    ans=n*n-ans;
    printf("%lld\n",ans);
}
void clear(){
    for(int i=1;i<=n;i++){
        ls[i]=rs[i]=a[i]=0;
        q[i].clear();
    }
    n=0,top=0,ans=0;
}
#undef int 
int main(){
    int T=read();
    while(T--)in(),work(),clear();
    return 0;
}

D

一开始觉得 D 很分治

这个分治的过程是先根号分治预处理一下大于根号的那个唯一质因子

然后剩下的按位异或,会发现这个过程总共需要处理 \(O(n)\) 的前后缀

然后每次处理跨过区间端点的答案,这个很简单,往左枚举前缀找后缀就可以

这个总的过程实现精细一些是个 \(O(n\log n)\) 的复杂度,

要用 bitset 存大概 \(150\) 位的长度,所以会挂一个比较大的常数,算上预处理就很草单了

正解其实是哈希

这个哈希注意是要维护奇偶性的,也就是奇数算偶数不算

这个就非常适合随机异或,因为异或恰好也有奇数算偶数不算的

这个也是同理,所以只需要扫描线,找到一个点问前面有多少个这样的数

总时间复杂度是 \(O(n\log n)\),正式做的这一部分是 \(O(n)\) 的,复杂度瓶颈在预处理

点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define int long long 
const int o=1e6+22;
mt19937_64 mk(time(0));
int p[o],h[o],a[o];
unordered_map<int,int>q,H;
int read(){
    int i=1,j=0;
    char ch=getchar();
    while(ch>'9'||ch<'0'){
        if(ch=='-')i=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9'){
        j=j*10+ch-48;
        ch=getchar();
    }
    return i*j;
}
int rand(int l,int r){
    uniform_int_distribution<> dis(l,r);
    return dis(mk);
}
void pre(int n){
    H[0]=1;
    for(int i=2;i<=n;i++){
        if(!p[i]){
            h[i]=rand(1,LLONG_MAX);
            for(int j=i+i;j<=n;j+=i){
                p[j]=1;
                h[j]=h[j/i]^h[i];
            }
        }
    }
}
void solve(){
    int n=read(),X=read(),ans=0,now=0;
    for(int i=1;i<=n;i++)a[i]=read();
    q[now]++;
    for(int i=1;i<=n;i++){
        now^=h[a[i]];
        if(q.find(now^h[X])!=q.end())ans+=q[now^h[X]];
        q[now]++;
    }
    printf("%lld\n",ans);
}
#undef int 
int main(){
    pre(1e6);
    solve();
    return 0;
}

不过说句闲话,嘴巴确实很简单,补题确实因为码力不够很尴尬
而且思维不到位也很尴尬

posted @ 2026-03-22 21:10  2K22  阅读(2)  评论(0)    收藏  举报