A-Permutation

链接:https://ac.nowcoder.com/acm/contest/5675/A
题意:不难发现,从 1 开始选,能选 2 的倍数就选 2∗x%n,能选 3 的倍数就选 3∗x%n,不能选就输出 −1就行。
思路:直接暴力模拟就好了
代码:

#include <iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long ll;
int flag[1000010];
int a[1000100];
int main()
{
    int t,n;
    cin>>t;
    while(t--)
    {
        int ans=1;
        memset(flag,0,sizeof flag);
        cin>>n;
            flag[1]=1;
            int x=1;
            a[0]=1;
           for(int i=1;i<=n-2;i++)
           {
               if(x*2<n&&flag[x*2]==0)
               {
                   flag[x*2]=1;
                   a[ans]=x*2;
                   x=x*2;
                   ans++;
               }
               else if(x*2%n<n&&flag[x*2%n]==0)
               {
                   flag[x*2%n]=1;
                   a[ans]=x*2%n;
                   x=x*2%n;
                   ans++;
               }
               else if(x*3%n<n&&flag[x*3%n]==0)
               {
                   flag[x*3%n]=1;
                   a[ans]=x*3%n;
                   x=x*3%n;
                   ans++;
               }
           }
           if(ans==n-1)
           {
               for(int i=0;i<ans-1;i++)
               {
                   cout<<a[i]<<" ";
               }
               cout<<a[ans-1]<<endl;
           }
           else cout<<"-1"<<endl;
    }
    return 0;
}

E-Game

链接:https://ac.nowcoder.com/acm/contest/5675/E
题意:积木,可以向左推某一行,如果下面空了就会向下掉,求最低高度。
思路:赛后发现果然是水题,直接求前缀和,每次能获得的最大高度就是 (sum−1)/i+1,这个可能不好理解,其实就等于sum/i上取整。
代码:

#include <iostream>
#include <cmath>
#include <algorithm>
using namespace std;
int T,n,a,ans;
double sum;
int main()
{
    cin>>T;
    while(T--){
        cin>>n;sum=0;ans=0;
        for(int i=1;i<=n;i++){
            cin>>a;
            sum+=a;
            int temp = ceil(sum/i);
            ans = max(ans,temp);
        }
        cout<<ans<<endl;
    }
    return 0;
}

I-Tournament

链接:https://ac.nowcoder.com/acm/contest/5675/I
题意:您正在安排比赛。有n个球队。 每一对球队有n(n−1)/2个比赛。每天安排一场比赛。对于每支球队,它将在第一场比赛举行的当天到达,并在最后一场比赛结束后离开。
例如,有3个团队,日程表是(1,2),(1,3),(2,3)。 一队将在第一天到达,在第二天离开。它将停留两天。 第二小组将停留三天。 第三队将停留两天。求一个安排表,以减少他们停留的总天数。
思路:
有n个人的日子,至少一天,有至少n-1个人的日子,至少四天。依次类推,可以得到个多下界。 同时还有另外一个下界,有3个人的日子,至少n(n-1)/2-2天,依次类推。
我们希望n号队伍最迟来(n号肯定是最后走的),又希望1号最早走(1号肯定最早来的),所以中间肯定是(1,n)。
仔细想想n-1和2是不是也是这样?以此类推,一直到n/2,都可以这样类比。
由此得:
1,首先把n个人分成两半
2,然后让前一半的人开始打比赛
3,然后让前一半的人和后一半的人打比赛
4,然后后一半的人开始打比赛
代码:

#include <cstdio>
int T,n,i,j;
int main(){
    scanf("%d",&T);
    while(T--){
        scanf("%d",&n);
        //1~n/2
        for(i=2;i<=n/2;++i)
            for(j=1;j<i;++j)
                printf("%d %d\n",j,i);
        //1~n/2 versus n/2+1~n    upper half    
        for(i=n/2+1;i<n;++i)
            for(j=1;j<=n-i;++j)
                printf("%d %d\n",j,i);
        //1~n/2 versus n/2+1~n    lower half    
        for(i=1;i<=n/2;++i)
            for(j=n-i+1;j<=n;++j)
                printf("%d %d\n",i,j);
        //n/2+1~n
        for(i=n/2+1;i<n;++i)
            for(j=i+1;j<=n;++j)
                printf("%d %d\n",i,j);                    
    }
}

J-Identical Trees

链接:https://ac.nowcoder.com/acm/contest/5675/J
思路:
我们从两个树的根开始递归下去,设dp[l][r]为T1的l为根的子树,和T2的r为根的子树的最小代价。
然后往上合并的时候相当于一个二分图最小匹配。

先用树hash判同构,然后用最小费用最大流找到最小代价即可。
代码:(慢慢补,还不太会)