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判同构,然后用最小费用最大流找到最小代价即可。
代码:(慢慢补,还不太会)