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;
}
posted @ 2021-08-01 12:14  七铭的魔法师  阅读(145)  评论(0编辑  收藏  举报