2021百度之星初赛第一场
2021百度之星初赛第一场
A
如果学姐讲题而且在能力范围内就补
C - 鸽子
简单dp, 没时间写了, 被毒瘤数据结构卡了。
设dp[j]为当前枚举的操作(含之前枚举过的操作)上,对于第j个位置的最小暗箱操作次数。
如果不可行设dp[j]=-1, 初始化dp[k]=0。
枚举当前操作时,不妨另当前允许交换的为位置u, v
对于u, v位置之外的dp值,由于我们要暗箱操作的次数尽可能地小, 所以选择操作, 所以dp值不变, 不需要更改。
对于u, v, 如果dp[u]=-1,dp[v]=-1,那么什么也不做。
如果dp[u]!=-1&&dp[v]==-1, 那么dp[v]=dp[u];
...
四种情况,代码里列的很清楚。
int dp[100005];
void solve(){
int n, m, k, u, v;
scanf("%d%d%d",&n,&m,&k);
fill(dp+1, dp+n+1,-1);
dp[k]=0;
while(m--){
scanf("%d%d",&u,&v);
if(dp[u]==-1&&dp[v]==-1) continue;
else if(dp[u]==-1&&dp[v]!=-1){
dp[u]=dp[v];
dp[v]+=1;
}
else if(dp[u]!=-1&&dp[v]==-1){
dp[v]=dp[u];
dp[u]+=1;
}
else{
int tmp1=dp[v], tmp2=dp[u];
dp[v]=min(dp[v]+1, tmp2);
dp[u]=min(dp[u]+1, tmp1);
}
}
for(int i=1;i<=n;++i){
printf("%d", dp[i]);
if(i!=n) putchar(' ');
}
puts("");
}
int main(){
int t;
scanf("%d", &t);
while(t--)
solve();
return 0;
}
D - 萌新
对于两个正数a, b,求出使它们同余地最小模数c和最大模数c。要求2<=c<=max(a, b)。存在输出-1。
为了方便处理,我们让a大于等于b。
如果a, b模c同余, 那么a=k*c+b。也就是说c必然是k*c的一个因子。
如果k*c=0,一般而言c最小为1,可以任意大。但是要求c大于1, 所以最小为2最大为a。不过a=b=1的情况要特判。
如果k*c=1, 那么去全为-1
如果k*c>1,最大为k*c,最小枚举因子即可。
void solve() {
int a, b;
scanf("%d%d", &a, &b);
if (a < b)
swap(a, b);
ll dif = a - b;
ll minn = dif, maxn = dif;
if (a == 1 && b == 1) {
printf("-1 -1\n");
return;
}
if (dif == 0) {
printf("2 %d\n", a);
return;
}
if (dif == 1) {
printf("-1 -1\n");
return;
}
for (ll i = 2; i * i <= dif; ++i) {
if (!(dif % i)) {
minn = min(minn, i);
break;
}
}
printf("%d %d\n", (int)minn, (int)maxn);
}
int main() {
int t;
scanf("%d", &t);
while (t--)
solve();
return 0;
}
F - 毒瘤数据结构题
傻逼题,用数据结构的被毒瘤了。
也是经验不够,5e6的数据算一算就发现O(nlogn)的算法花费最大为5e6220=2e8左右,还要考虑维护线段树的常数。
想法是给原序列首端和末端添两个0,然后用数组链式维护序列中每个0出现的位置即可。O(n), hdu的评测机好像慢了些,快读被卡了,要挂超级快读。
bool aa[5000005];
int nex[5000005],pre[5000005];
int main(){
int n,op,x;
Read(n);
pre[n+1]=n;nex[0]=1;
for(int i=1;i<=n;++i) {
nex[i]=i+1;
pre[i]=i-1;
}
for(int i=1;i<=n;++i){
int op,x;
Read(op);Read(x);
if(op==1){
if(aa[x]) continue;
nex[pre[x]]=nex[x];
pre[nex[x]]=pre[x];
aa[x]=1;
}
else{
if(x==nex[0]){
printf("%d\n",nex[nex[0]]);
}
else printf("%d\n",nex[0]);
}
}
return 0;
}
H. 猎人杀
模拟题, 开始题意理解错了, 又浪费了时间==
vector<int> aa[55];
int pos[55];
bool bb[55],dead[55];
void solve(){
for(int i=1;i<=50;++i){
aa[i].clear();
pos[i]=bb[i]=dead[i]=0;
}
int n,u;
scanf("%d", &n);
for(int i=1;i<=n;++i){
scanf("%d", bb+i);
if(bb[i]==1) u=i;
}
int x;
for(int i=1;i<=n;++i){
for(int j=1;j<=n;++j){
scanf("%d", &x);
aa[i].push_back(x);
}
}
int lan=u;
if(aa[lan][0]==lan){
puts("lieren");
return;
}
while(1){
while(dead[ aa[u][ pos[u] ]]==1) ++pos[u];
int v=aa[u][ pos[u] ];
--n;
dead[v]=1;
if(v==lan){
puts("lieren");
return;
}
if(n==2){
puts("langren");
return;
}
u=v;
}
return;
}
int main(){
int t;
scanf("%d",&t);
while(t--) solve();
return 0;
}