Atcoder Beginner Contest 422 A-F
A
CODE
#include<bits/stdc++.h>
#define usetime() (double)clock () / CLOCKS_PER_SEC * 1000.0
using namespace std;
typedef long long LL;
void read(int& x){
char c;
bool f=0;
while((c=getchar())<48) f|=(c==45);
x=c-48;
while((c=getchar())>47) x=(x<<3)+(x<<1)+c-48;
x=(f ? -x : x);
}
int a,b;
int main(){
read(a),read(b);
++b;
if(b>8) b=1,++a;
printf("%d-%d",a,b);
return 0;
}
//^o^
B
这里指的是上下左右相邻的四个格子,别理解错了
CODE
#include<bits/stdc++.h>
#define usetime() (double)clock () / CLOCKS_PER_SEC * 1000.0
using namespace std;
typedef long long LL;
const int maxn=25;
void read(int& x){
char c;
bool f=0;
while((c=getchar())<48) f|=(c==45);
x=c-48;
while((c=getchar())>47) x=(x<<3)+(x<<1)+c-48;
x=(f ? -x : x);
}
void read(char& c){
do{
c=getchar();
}while(c==32||c==10||c==13);
}
char mp[maxn][maxn];
int n,m;
int wx[4]={0,0,-1,1},wy[4]={-1,1,0,0};
int main(){
read(n),read(m);
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
read(mp[i][j]);
}
}
bool ans=1;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(mp[i][j]=='.') continue;
int cnt=0;
for(int k=0;k<4;k++){
int xi=i+wx[k],yi=j+wy[k];
if(xi>=1&&xi<=n&&yi>=1&&yi<=m){
cnt+=mp[xi][yi]=='#';
}
}
ans&=(cnt==2||cnt==4);
}
}
if(ans) printf("Yes");
else printf("No");
return 0;
}
//^o^
C
耗时 \(1\) 小时,交了 \(6\) 发,没做出来 TT
首先肯定把 \(B\) 都用光,然后考虑 \(A\) 和 \(C\)
其实肯定有公式的,不过也可以无脑三分
代码写的是三分(我把右边界写错赛时没调出来)
CODE
#include<bits/stdc++.h>
#define usetime() (double)clock () / CLOCKS_PER_SEC * 1000.0
using namespace std;
typedef long long LL;
const int maxn=25;
void read(int& x){
char c;
bool f=0;
while((c=getchar())<48) f|=(c==45);
x=c-48;
while((c=getchar())>47) x=(x<<3)+(x<<1)+c-48;
x=(f ? -x : x);
}
void read(char& c){
do{
c=getchar();
}while(c==32||c==10||c==13);
}
char mp[maxn][maxn];
int n,m;
int wx[4]={0,0,-1,1},wy[4]={-1,1,0,0};
int main(){
read(n),read(m);
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
read(mp[i][j]);
}
}
bool ans=1;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(mp[i][j]=='.') continue;
int cnt=0;
for(int k=0;k<4;k++){
int xi=i+wx[k],yi=j+wy[k];
if(xi>=1&&xi<=n&&yi>=1&&yi<=m){
cnt+=mp[xi][yi]=='#';
}
}
ans&=(cnt==2||cnt==4);
}
}
if(ans) printf("Yes");
else printf("No");
return 0;
}
//^o^
\(upd\,\,on\,\,2025.9.9\)
更好的做法,本来是从一位巨佬的交谈中得知的,然后发现和官解是一样的
他说他是凑出来的,这里来证明这种做法
先给公式:
由于 \(ABC\) , \(ACC\) , \(AAC\) 都需要至少一个 \(A\) 和 \(C\)
所以 \(Min(a,c)\) 是能组成个数的上限
然后考虑不能达到上限的情况
即 \(Min(a,c)>(a+b+c)/3\) ,也就是说,此时 \(a,c\) 均大于 \((a+b+c)/3\)
那么只要一定可以组成 \((a+b+c)/3\) 个形如 \(A?C\) 的框架
并将剩下的东西填到中间去,由于保证可以存在 \((a+b+c)/3\) 个三元组,那么填进去的东西也一定是够的
CODE
#include<bits/stdc++.h>
#define usetime() (double)clock () / CLOCKS_PER_SEC * 1000.0
using namespace std;
typedef long long LL;
void read(int& x){
char c;
bool f=0;
while((c=getchar())<48) f|=(c==45);
x=c-48;
while((c=getchar())>47) x=(x<<3)+(x<<1)+c-48;
x=(f ? -x : x);
}
int t;
int a,b,c;
int main(){
read(t);
while(t--){
read(a),read(b),read(c);
printf("%lld\n",min((LL)min(a,c),((LL)a+b+c)/3));
}
return 0;
}
//^o^
D
看到这个,很容易想到分治
分治的时候尽量把两边弄均匀
只有在奇数的时候,分配时会产生 \(1\) 的差值
发现答案不是 \(0\) 就是 \(1\)
CODE
#include<bits/stdc++.h>
#define usetime() (double)clock () / CLOCKS_PER_SEC * 1000.0
using namespace std;
typedef long long LL;
const int maxn=2e6+5;
const int max2=25;
void read(int& x){
char c;
bool f=0;
while((c=getchar())<48) f|=(c==45);
x=c-48;
while((c=getchar())>47) x=(x<<3)+(x<<1)+c-48;
x=(f ? -x : x);
}
int n,k;
int ans=0;
int a[maxn];
void solve(int l,int r,int p,int g){
if(l==r){
a[l]+=p;
return;
}
int mid=(l+r)>>1;
ans|=(p&1);
solve(l,mid,p/2,g+1),solve(mid+1,r,(p+1)/2,g+1);
}
int main(){
read(n),read(k);
n=(1<<n);
int p=k/n;
k%=n;
solve(1,n,k,0);
printf("%d\n",ans);
for(int i=1;i<=n;i++){
printf("%d ",p+a[i]);
}
return 0;
}
//^o^
E
随机找两个点,这两个点在一条覆盖一半点的直线上的概率约为 \(\frac{1}{4}\)
\(5e5\) 的数据范围,找个 \(1000\) 次绝对够了
CODE
#include<bits/stdc++.h>
#define usetime() (double)clock () / CLOCKS_PER_SEC * 1000.0
using namespace std;
typedef long long LL;
mt19937 rd(time(NULL));
const int maxn=5e5+5;
void read(int& x){
char c;
bool f=0;
while((c=getchar())<48) f|=(c==45);
x=c-48;
while((c=getchar())>47) x=(x<<3)+(x<<1)+c-48;
x=(f ? -x : x);
}
int n;
int x[maxn],y[maxn];
int main(){
read(n);
for(int i=1;i<=n;i++){
read(x[i]),read(y[i]);
}
for(int i=1;i<=1000;i++){
int a=rd()%n+1,b=rd()%n+1;
while(a==b) b=rd()%n+1;
LL p=y[b]-y[a],q=x[a]-x[b];
LL c=-1ll*p*x[a]-1ll*q*y[a];
//cout<<a<<' '<<b<<' '<<p<<' '<<q<<' '<<c<<endl;
int cnt=0;
for(int j=1;j<=n;j++){
if(p*x[j]+q*y[j]+c==0){
//cout<<j<<' ';
++cnt;
}
}
//cout<<endl;
if(cnt>=(n+1)/2){
printf("Yes\n%lld %lld %lld",p,q,c);
return 0;
}
}
printf("No");
return 0;
}
//^o^
F
\(upd\,\, on \,\,2025.9.9\)
由于同时和点权和路径长度产生联系,所以是不能用 \(dijkstra\) 解决的
对于一条长为 \(n\) 的路径,我们发现它的点权的权值是这样的
于是我们可以设计状态 \(dp[i][j]\) 表示点 \(j\) 作为路径长度为 \(i\) 的路径的起点,其从 \(1\) 开始到 \(j\) 所花费的最小油费
即它的点权的权值应该为 \(i\)
状态转移显然:
CODE
#include<bits/stdc++.h>
#define usetime() (double)clock () / CLOCKS_PER_SEC * 1000.0
using namespace std;
typedef long long LL;
const int maxn=5005,maxm=5005;
void read(int& x){
char c;
bool f=0;
while((c=getchar())<48) f|=(c==45);
x=c-48;
while((c=getchar())>47) x=(x<<3)+(x<<1)+c-48;
x=(f ? -x : x);
}
int head[maxn],nxt[maxm<<1],e[maxm<<1];
int mp_cnt;
void init_mp(){
memset(head,-1,sizeof(head));
mp_cnt=-1;
}
void add_edge(int u,int v){
e[++mp_cnt]=v;
nxt[mp_cnt]=head[u];
head[u]=mp_cnt;
}
struct node{
int u;
LL p;
};
int n,m;
int w[maxn];
LL dp[maxn][maxn];
int main(){
read(n),read(m);
init_mp();
for(int i=1;i<=n;i++) read(w[i]);
int u,v;
for(int i=1;i<=m;i++){
read(u),read(v);
add_edge(u,v),add_edge(v,u);
}
queue<int> q;
memset(dp,0x3f,sizeof(dp));
for(int i=0;i<n;i++) dp[i][1]=1ll*i*w[1];
for(int i=n-2;i>=0;i--){
for(int j=1;j<=n;j++){
for(int k=head[j];~k;k=nxt[k]){
int v=e[k];
dp[i][j]=min(dp[i][j],dp[i+1][v]+1ll*i*w[j]);
}
}
}
for(int i=1;i<=n;i++) printf("%lld\n",dp[0][i]);
return 0;
}
//^o^

浙公网安备 33010602011771号