AtCoder Beginner Contest 374
ABC374 A - Takahashi san 2
代码(签到题)
#include <cstdio>
#include <cctype>
#include <cstring>
#include <cmath>
#include <queue>
using namespace std;
int iut(){
int ans=0,f=1; char c=getchar();
while (!isdigit(c)) f=(c=='-')?-f:f,c=getchar();
while (isdigit(c)) ans=ans*10+c-48,c=getchar();
return ans*f;
}
void print(int ans){
if (ans>9) print(ans/10);
putchar(ans%10+48);
}
int main(){
char s[111]; int len;
scanf("%s",s+1),len=strlen(s+1);
if (s[len-2]=='s'&&s[len-1]=='a'&&s[len]=='n'){
printf("Yes");
}else printf("No");
return 0;
}
ABC374 B - Unvarnished Report
代码(签到题)
#include <cstdio>
#include <cctype>
#include <cstring>
#include <cmath>
#include <queue>
using namespace std;
char s[111],t[111]; int n,m;
int iut(){
int ans=0,f=1; char c=getchar();
while (!isdigit(c)) f=(c=='-')?-f:f,c=getchar();
while (isdigit(c)) ans=ans*10+c-48,c=getchar();
return ans*f;
}
void print(int ans){
if (ans>9) print(ans/10);
putchar(ans%10+48);
}
int main(){
scanf("%s",s+1),n=strlen(s+1);
scanf("%s",t+1),m=strlen(t+1);
for (int i=1;i<=n||i<=m;++i)
if (s[i]!=t[i]){
return !printf("%d",i);
}
return !printf("0");
}
ABC374 C - Separated Lunch
代码(签到题)
#include <cstdio>
#include <cctype>
#include <cstring>
#include <cmath>
#include <queue>
#include <algorithm>
using namespace std;
int n,a[111],ans,sum;
int iut(){
int ans=0,f=1; char c=getchar();
while (!isdigit(c)) f=(c=='-')?-f:f,c=getchar();
while (isdigit(c)) ans=ans*10+c-48,c=getchar();
return ans*f;
}
void print(int ans){
if (ans>9) print(ans/10);
putchar(ans%10+48);
}
int main(){
n=iut();
for (int i=0;i<n;++i) a[i]=iut(),sum+=a[i];
ans=sum;
for (int i=2;i<(1<<n);i+=2){
int now=0;
for (int j=0;j<n;++j)
if ((i>>j)&1) now+=a[j];
ans=min(ans,max(now,sum-now));
}
return !printf("%d",ans);
}
ABC374 D - Laser Marking
代码(签到题)
#include <cstdio>
#include <cctype>
#include <cstring>
#include <cmath>
#include <queue>
#include <algorithm>
using namespace std;
const int N=111; double ans=1e18;
int n,v1,v2,x[N][2],y[N][2],rk[N];
int iut(){
int ans=0,f=1; char c=getchar();
while (!isdigit(c)) f=(c=='-')?-f:f,c=getchar();
while (isdigit(c)) ans=ans*10+c-48,c=getchar();
return ans*f;
}
void print(int ans){
if (ans>9) print(ans/10);
putchar(ans%10+48);
}
double o(int lx,int ly,int rx,int ry){return sqrt((rx-lx)*(rx-lx)+(ry-ly)*(ry-ly));}
int main(){
n=iut(),v1=iut(),v2=iut();
for (int i=1;i<=n;++i){
x[i][0]=iut(),y[i][0]=iut();
x[i][1]=iut(),y[i][1]=iut();
rk[i]=i;
}
do{
for (int i=0;i<(1<<n);++i){
int lstx=0,lsty=0; double now=0;
for (int j=1;j<=n;++j){
int z=(i>>(j-1))&1;
now+=o(lstx,lsty,x[rk[j]][z],y[rk[j]][z])/v1;
lstx=x[rk[j]][z^1],lsty=y[rk[j]][z^1];
now+=o(lstx,lsty,x[rk[j]][z],y[rk[j]][z])/v2;
}
ans=min(ans,now);
}
}while (next_permutation(rk+1,rk+1+n));
printf("%.12lf",ans);
}
ABC374 E - Sensor Optimization Dilemma 2
分析
二分答案,这样就变成每种机器有最低产量限制,且让总费用最小,而单个最小值的枚举机器个数是在 \(\max\{a_i,b_i\}\) 范围内的,考场写了假的三分故意扩大 eps 然后过了
代码
#include <cstdio>
#include <cctype>
#include <cstring>
#include <cmath>
#include <queue>
#include <algorithm>
using namespace std;
const int N=111;
typedef long long lll;
int w[N][2],c[N][2],n,X;
int iut(){
int ans=0,f=1; char c=getchar();
while (!isdigit(c)) f=(c=='-')?-f:f,c=getchar();
while (isdigit(c)) ans=ans*10+c-48,c=getchar();
return ans*f;
}
void print(int ans){
if (ans>9) print(ans/10);
putchar(ans%10+48);
}
lll calc(lll j,int i,int mid){
if (mid>j*c[i][0]) return j*w[i][0]+(mid-j*c[i][0]+c[i][1]-1)/c[i][1]*w[i][1];
else return j*w[i][0];
}
bool check(int mid){
lll sum=0;
for (int i=1;i<=n;++i){
lll now=1e18,lim=(mid+c[i][0]-1)/c[i][0];
for (int j=0;j<=c[i][1];++j) now=min(now,calc(j,i,mid));
for (int j=lim;j>=lim-c[i][0]&&j>=0;--j) now=min(now,calc(j,i,mid));
sum+=now;
if (sum>X) return 0;
}
return 1;
}
int main(){
n=iut(),X=iut();
for (int i=1;i<=n;++i){
c[i][0]=iut(),w[i][0]=iut();
c[i][1]=iut(),w[i][1]=iut();
if (c[i][0]<c[i][1]) swap(c[i][0],c[i][1]),swap(w[i][0],w[i][1]);
}
int l=0,r=0x3f3f3f3f;
while (l<r){
int mid=(l+r+1)>>1;
if (check(mid)) l=mid;
else r=mid-1;
}
return !printf("%d",l);
}
ABC374 F - Shipping
分析
本题动态规划一定要利用时刻,而有效的时刻就是 \(T_i+kX\) 共 \(O(n^2)\) 个。
设 \(dp[i][j]\) 表示时刻 \(i\) 或以前已经让前 \(j\) 艘船通过的最小值,直接 \(O(n^3k)\) 即可
代码
#include <cstdio>
#include <cctype>
#include <cstring>
#include <cmath>
#include <queue>
#include <algorithm>
using namespace std;
const int N=111;
typedef long long lll;
lll n,m,k,X,a[N],dp[N*N][N],b[N*N];
lll iut(){
lll ans=0,f=1; char c=getchar();
while (!isdigit(c)) f=(c=='-')?-f:f,c=getchar();
while (isdigit(c)) ans=ans*10+c-48,c=getchar();
return ans*f;
}
int main(){
n=iut(),k=iut(),X=iut();
for (int i=1;i<=n;++i){
a[i]=iut();
for (int j=0;j<n;++j) b[++m]=a[i]+j*X;
}
sort(b+1,b+1+m),m=unique(b+1,b+1+m)-b-1;
for (int i=0;i<=m;++i)
for (int j=0;j<=n;++j) dp[i][j]=1e18;
dp[0][0]=0,b[0]=-X;
for (int i=1,I=0;i<=m;++i){
while (I<=m&&b[I]+X<=b[i]) ++I; --I;
for (int j=0;j<=n;++j){
if (b[i]<a[j]) break;
dp[i][j]=dp[i-1][j];
lll sum=0;
for (int o=0;o<=k&&o<=j;++o)
dp[i][j]=min(dp[i][j],dp[I][j-o]+sum),sum+=b[i]-a[j-o];
}
}
return !printf("%lld",dp[m][n]);
}
ABC374 G - Only One Product Name
分析
最多有 \(26^2\) 个点的有向图,求最小可相交路径覆盖,由于可相交,不妨先将该有向图缩点成 DAG,
在新图传递闭包,答案为新图点数减去最大匹配数
代码
#include <iostream>
#include <string>
#include <stack>
#include <bitset>
using namespace std;
const int N=911; bitset<N>a[N]; string str[N];
struct node{int y,next;}e[N*N]; stack<int>st;
int dfn[N],low[N],v[N],col[N],tot,cnt,n,upd,link[N],et=1,ans,as[N];
void tarjan(int x){
dfn[x]=low[x]=++tot,v[x]=1,st.push(x);
for (int i=as[x];i;i=e[i].next)
if (!dfn[e[i].y]){
tarjan(e[i].y);
low[x]=min(low[x],low[e[i].y]);
}else if (v[e[i].y]) low[x]=min(low[x],dfn[e[i].y]);
if (dfn[x]==low[x]){
int y; ++cnt;
do{
y=st.top(); st.pop();
col[y]=cnt,v[y]=0;
}while (y!=x);
}
}
bool match(int x){
for (int y=1;y<=cnt;++y)
if (a[x][y]&&v[y]!=upd){
v[y]=upd;
int q=link[y];
link[y]=x;
if (!q||match(q)) return 1;
link[y]=q;
}
return 0;
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
cin>>n;
for (int i=1;i<=n;++i) cin>>str[i];
for (int i=1;i<=n;++i)
for (int j=1;j<=n;++j)
if (str[j][0]==str[i][1]){
e[++et]=(node){j,as[i]},as[i]=et;
}
for (int i=1;i<=n;++i) if (!dfn[i]) tarjan(i);
for (int i=1;i<=n;++i)
for (int j=as[i];j;j=e[j].next)
if (col[i]!=col[e[j].y]) a[col[i]][col[e[j].y]]=1;
for (int k=1;k<=cnt;++k)
for (int i=1;i<=cnt;++i)
if (a[i][k]) a[i]|=a[k];
for (int i=1;i<=cnt;++i){
++upd;
if (match(i)) ++ans;
}
cout<<cnt-ans;
return 0;
}