Codeforces Round #580 (Div. 2)

- 日理万妓 2023-06-04 11:58 83阅读 0赞

Solutions


A. Choose Two Numbers

题意:
给出\(A,B\)两个集合,\(A,B\) 集合分别选一个数\(a,b\) ,使得\(a+b\notin\ A,B\)
思路:
每个集合选出最大值,必定满足条件。emmmmm比赛的时候傻了。

  1. //#define DEBUG
  2. #include<bits/stdc++.h>
  3. using namespace std;
  4. #define lson (rt<<1)
  5. #define rson (rt<<1|1)
  6. const int N=100010;
  7. const int inf=0X3f3f3f3f;
  8. const long long INF = 0x3f3f3f3f3f3f3f3f;
  9. const double eps = 1e-6;
  10. const double pi = acos(-1.0);
  11. const int mod = 1000000007;
  12. typedef long long ll;
  13. int a[110];
  14. int main() {
  15. #ifdef DEBUG
  16. freopen("in.txt","r",stdin);
  17. #endif
  18. int n,m,ans1,ans2;
  19. scanf("%d",&n);
  20. for(int i=1;i<=n;i++) scanf("%d",&a[i]);
  21. ans1=*max_element(a+1,a+n+1);
  22. scanf("%d",&m);
  23. for(int i=1;i<=m;i++) scanf("%d",&a[i]);
  24. ans2=*max_element(a+1,a+m+1);
  25. printf("%d %d\n",ans1,ans2);
  26. }

B. Make Product Equal One

题意:
给出\(a_1,a_2,\dots,a_n\),可以进行任意次操作:选择其中任意一个数\(+1,-1\),使得最后\(a_1{\ast}a_2{\ast}\dots{\ast}a_n=1\)。
思路:
负数就变为\(-1\),整数就变为\(1\),但是若负数个数为奇数,则需要有一个变为\(1\),但是存在\(0\)的话,则不需要。

  1. //#define DEBUG
  2. #include<bits/stdc++.h>
  3. using namespace std;
  4. #define lson (rt<<1)
  5. #define rson (rt<<1|1)
  6. const int N=100010;
  7. const int inf=0X3f3f3f3f;
  8. const long long INF = 0x3f3f3f3f3f3f3f3f;
  9. const double eps = 1e-6;
  10. const double pi = acos(-1.0);
  11. const int mod = 1000000007;
  12. typedef long long ll;
  13. int main() {
  14. #ifdef DEBUG
  15. freopen("in.txt","r",stdin);
  16. #endif
  17. int n;
  18. scanf("%d",&n);
  19. ll ans=0,ok=0,res=1;
  20. for(int i=1;i<=n;i++) {
  21. int x;
  22. scanf("%d",&x);
  23. if(x>=1) ans+=x-1;
  24. else if(x<0) ans+=-1-x,res*=-1;
  25. else if(!x) ans+=1,ok=1;
  26. }
  27. if(ok||res==1) printf("%lld\n",ans);
  28. else printf("%lld\n",ans+2);
  29. }

C. Almost Equal

题意:
给出数字\(n\),你需要安排的数为\(1\sim2n\),组成一个环。每连续\(n\)个数求一次和\(sum_i\),输出一个合法的序列,使得\({\forall}i,j,\ {\mid}sum_i-sum_j{\mid}{\leq}1\)
思路:
比赛时我构造出序列,然后队友写出\(check\) 代码,构造时发现分为两部分,右边最上面写一个最大的,左边最下面写次大的,然后左边再写次次大的,右边再写次次次大的,交替进行。可以理解为右边为先手,然后左边变为先手。构造完以后,用数组模拟成环,然后前缀和搞一搞模拟\(check\) 即可。
正解:
我们定义\(s_i=a_i+a_{i+1}+a_{i+2}+{\dots}+a_{i+n-1}\),
\(S_{i+1}-S_{i}=\left(a_{i+1}+a_{i+2}+a_{i+3}+\cdots+a_{i+n}\right)-\left(a_{i}+a_{i+1}+a_{i+2}+\cdots+a_{i+n-1}\right)=a_{i+n}-a_{i}\) 根据题意有\({\mid}a_{i+n}-a_i{\mid}{\leq}1\),因为\(a\)数组都是不同的,所以\({\mid}a_{i+n}-a_i{\mid}=1\)
则根据题意有:\(a_{i+n}-a_i,a_{i+n+1}-a_{i+1}\) 有相反的符号。 证:若他们都等于\(1\),则\(S_{i+2}-S_i=(S_{i+2}-S_{i+1})+(S_{i+1}-S_{i})=(a_{i+n+1}-a_{i+1})+(a_{i+n}-a_i)=2\),若都为\(-1\)也一样。因此,对于\(a_{i+n}-a_i\),他们是交替的\(1,-1,1,\dots\)。

  • 如果\(n\)为偶数,存在矛盾\(a_{i+n}-a_i=-(a_{(i+n)+n}-a_{i+n})\),但是由于交替,所以他们应该是相等的
  • 如果\(n\)为奇数,\(i:1{\sim}n\)

    • 若\(i\)为奇数,\(a_i=2i,a_{i+n}=2i-1\)
    • 若\(i\)为偶数,\(a_i=2i-1,a_{i+n}=2i\)

    //#define DEBUG

    include

    using namespace std;

    define lson (rt<<1)

    define rson (rt<<1|1)

    const int N=100010;
    const int inf=0X3f3f3f3f;
    const long long INF = 0x3f3f3f3f3f3f3f3f;
    const double eps = 1e-6;
    const double pi = acos(-1.0);
    const int mod = 1000000007;
    typedef long long ll;

    int a[N],b[N],c[4N];
    ll ans[4
    N];
    int main() {

    1. #ifdef DEBUG
    2. freopen("in.txt","r",stdin);
    3. #endif
    4. int n;
    5. scanf("%d",&n);
    6. bool flag=true;
    7. int cura=0,curb=0;
    8. int x=2*n;
    9. while(x) {
    10. if(flag) {
    11. b[++curb]=x--;
    12. a[++cura]=x--;
    13. } else {
    14. a[++cura]=x--;
    15. b[++curb]=x--;
    16. }
    17. flag=!flag;
    18. }
    19. int cur=0;
    20. for(int i=cura;i>=1;i--) c[++cur]=a[i];
    21. for(int i=curb;i>=1;i--) c[++cur]=b[i];
    22. int len=cur;
    23. for(int i=1;i<=len;i++) c[++cur]=c[i];
    24. //for(int i=1;i<=cur;i++) printf("%d\n",c[i]);
    25. set<ll> s;
    26. for(int i=1;i<=n;i++)ans[i]=ans[i-1]+c[i];
    27. s.insert(ans[n]);
    28. for(int i=n+1;i<=3*n;i++){
    29. ans[i]=ans[i-1]-c[i-n]+c[i];
    30. s.insert(ans[i]);
    31. }
    32. if(s.size()>2)puts("NO");
    33. else if(s.size()==2){
    34. set<ll>::iterator it=s.begin();
    35. ll s1,s2;
    36. s1=*it;
    37. it++;
    38. s2=*it;
    39. if(abs(s1-s2)!=1)puts("NO");
    40. else {
    41. puts("YES");
    42. for(int i=1;i<=2*n;i++)printf("%d%c",c[i],i==2*n?'\n':' ');
    43. }
    44. }
    45. else {
    46. puts("YES");
    47. for(int i=1;i<=2*n;i++)printf("%d%c",c[i],i==2*n?'\n':' ');
    48. }

    }

    //#define DEBUG

    include

    using namespace std;

    define lson (rt<<1)

    define rson (rt<<1|1)

    const int N=100010;
    const int inf=0X3f3f3f3f;
    const long long INF = 0x3f3f3f3f3f3f3f3f;
    const double eps = 1e-6;
    const double pi = acos(-1.0);
    const int mod = 1000000007;
    typedef long long ll;

    int a[2*N];
    int main() {

    1. #ifdef DEBUG
    2. freopen("in.txt","r",stdin);
    3. #endif
    4. int n;
    5. scanf("%d",&n);
    6. if(n%2==0) {puts("NO");return 0;}
    7. puts("YES");
    8. for(int i=1;i<=n;i++) {
    9. if(i&1) a[i]=2*i,a[i+n]=2*i-1;
    10. else a[i]=2*i-1,a[i+n]=2*i;
    11. }
    12. for(int i=1;i<=2*n;i++) printf("%d%c",a[i],i==2*n?'\n':' ');

    }

D. Shortest Cycle

题意:
给出\(a_1,a_2,{\dots},a_n\),当作图中的\(n\)个点,对于\({\forall}i,j(i{\neq}j),a_i\&a_j{\neq}0\),\(a_i\)和\(a_j\)连一条边,然后求最小环。
思路:
比赛时队友考虑二进制,都把\(60\)个位置画出来了。我也准备好\(floyd\)最小环了。但是沙雕了,感觉每个位置都连边,复杂度太大emmmmmm。其实二进制对应位置\(1\)的个数大于\(2\),那么最小环就是\(3\),然后最多\(120\)个点\(60\)条边(可能不确切),然后\(floyd\)跑最小环即可。
\(floyd\)求最小环:\(d[i][j]\)为\(i\)到\(j\)不包含\(k\)点的最短距离。所以对于当前\(k\),我们已经求得\(1{\sim}k-1\)的\(d[i][j]\),然后枚举\(1{\sim}k-1\)的\(d[i][j]\),然后更新答案,\(ans=min(ans,a[i][k]+a[k][j]+d[i][j])\),表示包含\(k\)的环,其中\(a\)数组为最初距离。

  1. //#define DEBUG
  2. #include<bits/stdc++.h>
  3. using namespace std;
  4. const int N=100010;
  5. const int inf=0X3f3f3f3f;
  6. const long long INF = 0x3f3f3f3f3f3f3f3f;
  7. const double eps = 1e-6;
  8. const double pi = acos(-1.0);
  9. const int mod = 1000000007;
  10. typedef long long ll;
  11. int ans=60;
  12. ll b[N],a[150][150],d[150][150];
  13. int tot;
  14. int main() {
  15. #ifdef DEBUG
  16. freopen("in.txt","r",stdin);
  17. #endif
  18. int n;
  19. scanf("%d",&n);
  20. ll x;
  21. for(int i=1;i<=n;i++) {
  22. scanf("%lld",&x);
  23. if(x) b[++tot]=x;
  24. }
  25. for(int i=0;i<=60;i++) {
  26. int cnt=0;
  27. for(int j=1;j<=tot;j++) {
  28. if(b[j]&(1ll<<i)) ++cnt;
  29. }
  30. if(cnt>=3) {puts("3");return 0;}
  31. }
  32. for(int i=1;i<=tot;i++) {
  33. for(int j=1;j<=tot;j++)
  34. if(i==j) d[i][j]=a[i][j]=0;
  35. else d[i][j]=a[i][j]=inf;
  36. }
  37. for(int i=1;i<=tot;i++) {
  38. for(int j=1;j<=tot;j++) {
  39. if(i==j) continue;
  40. if(b[i]&b[j]) a[i][j]=d[i][j]=1;
  41. }
  42. }
  43. //memcpy(d,a,sizeof(a));
  44. for(int k=1;k<=tot;k++) {
  45. for(int i=1;i<=k-1;i++) {
  46. for(int j=1;j<=k-1;j++)
  47. if(i!=j&&a[i][k]+a[k][j]+d[i][j]<ans)
  48. ans=a[i][k]+a[k][j]+d[i][j];
  49. }
  50. for(int i=1;i<=tot;i++) {
  51. for(int j=1;j<=tot;j++)
  52. if(d[i][j]>d[i][k]+d[k][j])
  53. d[i][j]=d[i][k]+d[k][j];
  54. }
  55. }
  56. if(ans==60) puts("-1");
  57. else printf("%d\n",ans);
  58. }

转载于:https://www.cnblogs.com/ACMerszl/p/11396093.html

发表评论

表情:
评论列表 (有 0 条评论,83人围观)

还没有评论,来说两句吧...

相关阅读

    相关 codeforces-round375-div2

    题目链接:[codeforces round 375 div2][] A题: 读一遍题目就知道是超级水的题目,,就是给你三个坐标,求三个坐标汇集到一个点所走的路程