补题若干(5)

[https://atcoder.jp/contests/abc394/tasks/abc394_e](图论+回文性质+最短路dj)

题意:

思路:

回文序列两边同时再加一个相同的字符依然是一个回文序列

因此将所有路径长度为1的和长度为2的回文路径压入优先队列

每次扩展:可到达u的u1和v可到达的v1判断能否组成回文序列即可

int n;
const int M=105;
vector<pii>e[M];
vector<pii>re[M];
int vis[M][M];
struct node{
    int u,v;
    int len;
    node(){}
    node(int a,int b,int c){
        u=a;
        v=b;
        len=c;
    }
    bool operator<(const node&a)const{
        return len>a.len;
    }
};
priority_queue<node>pq;

int ans[M][M];

void solve(){
    cin>>n;
    memset(ans,inf,sizeof ans);
    rep(i,1,n)ans[i][i]=0;

    rep(i,1,n){
        rep(j,1,n){
            char _;cin>>_;
            if(_=='-')continue;
            int __ = _ - 'a';
            e[i].pb({j,__});
            re[j].pb({i,__});
            // cerr<<i<<' '<<j<<endl;
            pq.push(node(i,j,1));
        }
    }
    

    rep(i,1,n){
        for(auto[v,_]:e[i]){
            for(auto[z,__]:e[v]){
                if(_ != __)continue;
                pq.push(node(i,z,2));
            }
        }
    }

    while(pq.size()){
        auto[u,v,len]=pq.top();
        pq.pop();
        if(vis[u][v])continue;
        vis[u][v]=1;
        ans[u][v]=min(ans[u][v],len);

        for(auto [u1,_]:re[u]){
            for(auto [v1,__]:e[v]){
                if(_==__ && len+2< ans[u1][v1]){
                    ans[u1][v1]=len+2;
                    pq.push(node(u1,v1,len+2));
                }
            }
        }
    }
    rep(i,1,n){
        rep(j,1,n){
            if(ans[i][j]<inf)cout<<ans[i][j]<<' ';
            else cout<<-1<<' ';
        }
        cout<<endl;
    }

}

[https://atcoder.jp/contests/abc389/tasks/abc389_e](二分+数学)

题意:

给定\(n\)个物品,每个物品买一次涨价\(2 \times P_i\)元 , 现在有\(m\) 元,求最多买多少件物品

思路:

二分\(x\) 表示只买价值小于等于\(x\)的 物品

可以\(O(1)\)算出每种物品买多少件

最后计算时加上剩下的钱除以\(x+1\)

int n,m;
const int M= 2e5+5;
int p[M];
int check(int k){
    int res = 0;
    rep(i,1,n){
        int t = (k+p[i])/(2ll*p[i]);
        if(t>=1e9 || t*t>=2e18 || 2e18/p[i] < t*t)return 0;
        res += t*t*p[i];
        if(res>m)return 0;
    }
    return 1;
}
void solve(){
    cin>>n>>m;
    rep(i,1,n)cin>>p[i];

    int res = 0;
    int l = 0, r= m;
    while(l<=r){
        int mid = l+r>>1;
        if(check(mid)){
            res=mid;
            l=mid+1;
        }else r=mid-1;
    }
    int ans = 0;
    rep(i,1,n){
        int t = (res+p[i])/(2*p[i]);
        m-=t*t*p[i];ans+=t;
    }
    cout<<ans + m/(res+1)<<endl;
}
posted @ 2025-11-13 14:35  Marinaco  阅读(5)  评论(0)    收藏  举报
//雪花飘落效果