补题若干(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;
}

浙公网安备 33010602011771号