A、 Permutation

题意:对于一个素数p,找到1-p-1的一种排列,使得每个排列的后一个数与前一个数的两倍或者三倍之间是关于p同余的关系。
思路:我们根据题意进行模拟,我们先把1放在第一个,然后我们找到满足要求的第二个数,也就是对前一个数乘2或乘3再modp,如果这个数还没被放进排列里面的话,那么就放进排列里面,如果找不到下一个数的话,那么就说明不存在这样的排列,输出-1.这里我是用一个栈和一个队列来进行模拟的。
代码

#include<iostream>
#include<cstring>
#include<algorithm>
#include<stack>
#include<queue>
using namespace std;
bool inq[1000010];
int main(){
    int t;
    cin>>t;
    while(t--){
        stack<int> st;
        queue<int> q;
        memset(inq,false,sizeof(inq));
        int p;
        cin>>p;
        st.push(1);
        q.push(1);
        inq[1]=true;
        bool flag=true;
        while(1){
            if(st.size()==p-1)  break;
            int tmp=st.top();
            int tmp1=2*tmp%p,tmp2=3*tmp%p;
        //    cout<<"tmp1:"<<tmp1<<"tmp2:"<<tmp2<<endl;
            if(inq[tmp1]==false){
                st.push(tmp1);
                q.push(tmp1);
                inq[tmp1]=true;
            }
            else if(inq[tmp2]==false){
                st.push(tmp2);
                q.push(tmp2);
                inq[tmp2]=true;
            }
            else{
                flag=false;
                break;
            }
        }
        if(!flag)  cout<<"-1"<<endl;
        else{
            while(!q.empty()){
                cout<<q.front()<<" ";
                q.pop();
            }
            cout<<endl;
        }
    }
    return 0;
}

D、Hearthstone Battlegrounds

题意:这个题目太太太太太太长了,比赛期间劝退了好多队伍(当然也还有我们队)。有两个玩家在玩一种游戏,这种游戏里每个玩家有四种仆人(每种仆人都是那种特扛揍的那种)。
1、有护盾加亡语
2、只有护盾
3、只有亡语
4、啥也没有
然后护盾可以免疫一切伤害,亡语在这个仆人死后会召唤出一种攻击力等于白给(1)的藤曼。只要有极低的可能性能赢就能赢。
思路:既然只有有极低的可能性能赢就能赢的话,那就把我们这方当作决定聪明的玩家,对面就是一个憨憨玩家。我们发现,我们要尽量让我们的藤曼去撞对方的护盾,而让对方的藤曼来攻击我们的仆人。但是为了让藤曼尽可能多,我们这方先用只有亡语的,让后在用护盾加亡语的,然后再用只有护盾的,最后硬刚啥也没有的。而对于对手,我们先也是放掉只有亡语的,然后在用掉啥也没有的,而把有护盾加亡语的和只有护盾的放到后两位。这样,我们积累了足够多的藤曼之后就可以破了对方的护盾了。也就是我们尽可能地多存放藤曼,让对方的啥也没有的仆人尽可能地攻击我们的护盾。我们把双方的准备阶段都防在prepare函数里面。
代码

#include<iostream>
using namespace std;
int a[6],b[6];
void prepare(){
    if(a[3])  a[5]++,a[3]--; //按亡语,护盾+亡语,护盾,啥也没有的顺序
    else if(a[1])  a[1]--,a[3]++;
    else if(a[2])  a[2]--,a[4]++;
    else  a[4]--;
    if(b[3])  b[3]--,b[5]++;  //按亡语,啥也没有,护盾+亡语,护盾的顺序
    else if(b[4])  b[4]--;
    else if(b[1])  b[3]++,b[1]--;
    else  b[2]--,b[4]++;
}
int main(){
    int t;
    cin>>t;
    while(t--){
        a[5]=b[5]=0;
        for(int i=1;i<=4;i++)  cin>>a[i];
        for(int i=1;i<=4;i++)  cin>>b[i];
        while(a[1]+a[2]+a[3]+a[4]&&b[1]+b[2]+b[3]+b[4]){
            prepare();  //双方先进行准备
            if(a[3]+a[4])  b[5]=0; //只要我方有仆人,对面的藤曼就等于白给
            if(a[5]&&b[1]+b[2]){   //只要我们有藤曼,就拿去撞对方的护盾
                if(b[1])  b[1]--,b[3]++;
                else  b[2]--,b[4]++;
                a[5]=0;
            }
        }
        if(b[1]+b[2]+b[3]+b[4]||!(a[1]+a[2]+a[3]+a[4])&&a[5]<=b[5])  cout<<"No"<<endl;
        else  cout<<"Yes"<<endl;
    }
    return 0;
}

I、Tournament

题意:有n个队伍,每个队伍都要与其他队伍之间进行一个比赛,问怎么样的安排才能使得每个队伍停留的时间尽可能地少。
思路:构造+贪心。我们将队伍直接分为两部分,前半部分和后半部分。前半部分先进行比赛,然后前半部分与后半部分之间进行比赛,最后是后半部分内部之间进行比赛。
代码

#include<iostream>
using namespace std;
int main(){
    int t;
    cin>>t;
    while(t--){
        int n;
        cin>>n;
        for(int i=2;i<=n/2;i++){  //前n/2个人之间互相进行比赛
            for(int j=1;j<i;j++){
                cout<<j<<" "<<i<<endl;
            }
        }
        for(int i=n/2+1;i<n;i++){  //后半部分与前半部分之间相互比赛
            for(int j=1;j<=n-i;j++){
                cout<<i<<" "<<j<<endl;
            }
        }
        for(int i=1;i<=n/2;i++){  //前半部分与后半部分之间相互比赛
            for(int j=n-i+1;j<=n;j++){
                cout<<j<<" "<<i<<endl;
            }
        }
        for(int i=n/2+1;i<n;i++){
            for(int j=i+1;j<=n;j++){
                cout<<j<<" "<<i<<endl;
            }
        }
    }
    return 0;
}

E、Game

题意:给出一个类似于俄罗斯方块那样高度的序列,问从右往左进行推滑块的操作(滑块会受重力作用掉落),问最后在所有滑块中高度最高最小化是多少。
思路:我们可以知道如果某个区间内后面的高度小于前面的高度的话,我们就没有必要进行操作,而如果是一个单调递增的区间的话,我们就可以将这个区间平均化,如果某个区间后面又是一个单调减的区间的话,那么其实对我们的ans没有影响,但是到了一定的程度上又对我们的区间会产生影响,因此问题就转化为求每个位置前缀和的平均,取最大前缀和平均即可。
代码

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<vector>
using namespace std;
typedef long long ll;
ll a[100010],pre[100010];
int main(){
    int T;
    scanf("%d",&T);
    while(T--){
        vector<ll> v;
        int n;
        scanf("%d",&n);
        pre[0]=0;
        ll ans=-1;
        for(int i=1;i<=n;i++){
            scanf("%lld",&a[i]);
            pre[i]=pre[i-1]+a[i];
            ll tmp=pre[i]/i;
            if(pre[i]%i!=0)  tmp++;
            ans=max(ans,tmp);
        }
        printf("%lld\n",ans);
    }
    return 0;
}