CODE FESTIVAL 2017 qual B 解题报告

Posted 惜取少年时

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CODE FESTIVAL 2017 qual B 解题报告相关的知识,希望对你有一定的参考价值。

做atcoder总是感到格外的智商不足……感觉atcoder比起codeforces来说题目普遍更有趣,更考验思维orz

C

题意:给出无向图,距离为3的点如果未连边,则可以连上一条边,问最多能连多少边。

解题思路:

易证距离(可以非简单路)为奇数的均可以连边。

如果是二分图,则图中不存在奇环,最终状态二分图两部的点彼此有连边。

非二分图的连通图一定存在奇环,则任意两点若初始距离非奇数,加上奇环之后距离就必可变为奇数。最终状态为完全图。

按最终状态的边数减去当下边数即可。

技术分享
  1 #include <cstdio>
  2 #include <iostream>
  3 #include <algorithm>
  4 #include <vector>
  5 #include <set>
  6 #include <map>
  7 #include <string>
  8 #include <cstring>
  9 #include <stack>
 10 #include <queue>
 11 #include <cmath>
 12 #include <ctime>
 13 #include <bitset>
 14 #include <utility>
 15 #include <assert.h>
 16 using namespace std;
 17 #define rank rankk
 18 #define mp make_pair
 19 #define pb push_back
 20 #define xo(a,b) ((b)&1?(a):0)
 21 #define tm tmp
 22 //#pragma comment(linker, "/STACK:1024000000,1024000000") 
 23 //#define LL ll
 24 typedef unsigned long long ull;
 25 typedef pair<int,int> pii;
 26 typedef long long ll;
 27 typedef pair<ll,int> pli;
 28 typedef pair<ll,ll> pll;
 29 const int INF=0x3f3f3f3f;
 30 const ll INFF=0x3f3f3f3f3f3f3f3fll;
 31 const int MAX=1e5+10;
 32 //const ll MAXN=2e8;
 33 //const int MAX_N=MAX;
 34 const ll MOD=998244353;
 35 //const long double pi=acos(-1.0);
 36 //const double eps=0.00000001;
 37 ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
 38 template<typename T>inline T abs(T a) {return a>0?a:-a;}
 39 template<class T> inline
 40 void read(T& num) {
 41     bool start=false,neg=false;
 42     char c;
 43     num=0;
 44     while((c=getchar())!=EOF) {
 45         if(c==-) start=neg=true;
 46         else if(c>=0 && c<=9) {
 47             start=true;
 48             num=num*10+c-0;
 49         } else if(start) break;
 50     }
 51     if(neg) num=-num;
 52 }
 53 inline ll powMM(ll a,ll b,ll M){
 54     ll ret=1;
 55     a%=M;
 56 //    b%=M;
 57     while (b){
 58         if (b&1) ret=ret*a%M;
 59         b>>=1;
 60         a=a*a%M;
 61     }
 62     return ret;
 63 }
 64 void open()
 65 {
 66 //    freopen("1009.in","r",stdin);
 67     freopen("out.txt","w",stdout);
 68 }
 69 int n,m,u,v;
 70 const int maxn=1e5+5;
 71 vector<int> G[maxn];
 72 int color[maxn];
 73 bool bipartite(int u)
 74 {
 75     for(int i=0;i<G[u].size();i++)
 76     {
 77         int v=G[u][i];
 78         if(color[v]==color[u])return false;
 79         if(!color[v])
 80         {
 81             color[v]=3-color[u];
 82             if(!bipartite(v))return false;
 83         }
 84     }
 85     return true;
 86 }
 87 int cnt1;
 88 int main()
 89 {
 90     scanf("%d%d",&n,&m);
 91     for(int i=1;i<=m;i++)
 92     {
 93         scanf("%d%d",&u,&v);G[u].pb(v);G[v].pb(u);
 94     }
 95     color[1]=1;
 96     if(bipartite(1))
 97     {
 98         for(int i=1;i<=n;i++)
 99             if(color[i]==1)++cnt1;
100         printf("%lld\n",1LL*(n-cnt1)*cnt1-m);
101     }
102     else printf("%lld\n",1LL*n*(n-1)/2LL-m);
103     return 0;
104 }
View Code

D

题意:给出01字符串,每次操作将101变为010,问最多做多少次操作。

解题思路:

注意到只有 若干个1+0+若干个1 的形式才能进行操作。

且实际上每次只有 x个1+0+1   1+0+x个1这部分会操作  像11011 实际上操作只能选择最初的4个数,或末尾的4个数 因为101操作后1的周围就被0包围,进行2次之后就与另一部分的1隔开了2个0,无法与之继续操作。

故考虑dp,只需要对每个 x个1+0+1 和1+0+x个1的dp即可。

x个1+0+1的操作次数为x。

技术分享
  1 #include <cstdio>
  2 #include <iostream>
  3 #include <algorithm>
  4 #include <vector>
  5 #include <set>
  6 #include <map>
  7 #include <string>
  8 #include <cstring>
  9 #include <stack>
 10 #include <queue>
 11 #include <cmath>
 12 #include <ctime>
 13 #include <bitset>
 14 #include <utility>
 15 #include <assert.h>
 16 using namespace std;
 17 #define rank rankk
 18 #define mp make_pair
 19 #define pb push_back
 20 #define xo(a,b) ((b)&1?(a):0)
 21 #define tm tmp
 22 //#pragma comment(linker, "/STACK:1024000000,1024000000") 
 23 //#define LL ll
 24 typedef unsigned long long ull;
 25 typedef pair<int,int> pii;
 26 typedef long long ll;
 27 typedef pair<ll,int> pli;
 28 typedef pair<ll,ll> pll;
 29 const int INF=0x3f3f3f3f;
 30 const ll INFF=0x3f3f3f3f3f3f3f3fll;
 31 const int MAX=5e5+10;
 32 //const ll MAXN=2e8;
 33 //const int MAX_N=MAX;
 34 const ll MOD=10007;
 35 //const long double pi=acos(-1.0);
 36 //const double eps=0.00000001;
 37 ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
 38 template<typename T>inline T abs(T a) {return a>0?a:-a;}
 39 template<class T> inline
 40 void read(T& num) {
 41     bool start=false,neg=false;
 42     char c;
 43     num=0;
 44     while((c=getchar())!=EOF) {
 45         if(c==-) start=neg=true;
 46         else if(c>=0 && c<=9) {
 47             start=true;
 48             num=num*10+c-0;
 49         } else if(start) break;
 50     }
 51     if(neg) num=-num;
 52 }
 53 inline ll powMM(ll a,ll b,ll M){
 54     ll ret=1;
 55     a%=M;
 56 //    b%=M;
 57     while (b){
 58         if (b&1) ret=ret*a%M;
 59         b>>=1;
 60         a=a*a%M;
 61     }
 62     return ret;
 63 }
 64 void open()
 65 {
 66 //    freopen("1009.in","r",stdin);
 67     freopen("out.txt","w",stdout);
 68 }
 69  
 70 int n;
 71 char a[MAX];
 72 int num[MAX],dp[MAX];
 73 int an,tem;
 74 int main()
 75 {
 76     scanf("%d",&n);
 77     scanf("%s",a+1);
 78     for(int i=1;i<=n;i++)
 79     {
 80         if(a[i]==1)
 81             num[i]=num[i-1]+1;
 82     }
 83     for(int i=n-1;i>=1;i--)
 84         if(a[i]==1)
 85             num[i]=max(num[i],num[i+1]);
 86     for(int i=2;i<=n-1;i++)
 87     {
 88         if(a[i]==0&&a[i-1]==1&&a[i+1]==1)
 89         {
 90             for(int j=1;j<=num[i+1];j++)
 91                 dp[i+j]=max(dp[i-2]+j,dp[i+j]);
 92             for(int j=1;j<=num[i-1];j++)
 93                 dp[i+1]=max(dp[i+1],dp[i-j-1]+j);
 94         }
 95         dp[i]=max(dp[i],dp[i-1]);
 96         an=max(an,dp[i]);
 97     }
 98     an=max(an,dp[n]);
 99     an=max(an,dp[n+1]);
100  
101     printf("%d\n",an);
102 }
View Code

E

题意:A个红球,B个蓝球,按前A个是红,后B个是蓝摆成一行。任选s\t两个位置,每次取出该行行首或s位置或t位置的球。所有的蓝、红球认为是一样的,问有多少种不同的取法。(两种取法认为是不同的,当且仅当存在某次取出,取出的球颜色不同)

以下代码是完全依照官方题解写的。

从(A,B)走到与第一个三角形的交点的距离是固定的(因为三角形边界的斜率为-1)方案数只与纵坐标之差有关。

同理到与第二个三角形的交点的方案数也只与纵坐标之差有关。下面考虑两个三角形位置和大小的选择。均为等腰直角三角形,设其直角边长度分别为x,y,则x>=s,y>=t,x+y<=A,取法个数为C(a-s-t+2,2)

(对于a个位置取出s+t个,加上边界的2个,选出2个位置,之后再加上s\t保证满足前面的限制条件,总方法即为此)

枚举s\t即可。

技术分享
 1 #include <cstdio>
 2 #include <iostream>
 3 #include <algorithm>
 4 #include <vector>
 5 #include <set>
 6 #include <map>
 7 #include <string>
 8 #include <cstring>
 9 #include <stack>
10 #include <queue>
11 #include <cmath>
12 #include <ctime>
13 #include <bitset>
14 #include <utility>
15 #include <assert.h>
16 using namespace std;
17 #define rank rankk
18 #define mp make_pair
19 #define pb push_back
20 #define xo(a,b) ((b)&1?(a):0)
21 #define tm tmp
22 //#pragma comment(linker, "/STACK:1024000000,1024000000") 
23 //#define LL ll
24 typedef unsigned long long ull;
25 typedef pair<int,int> pii;
26 typedef long long ll;
27 typedef pair<ll,int> pli;
28 typedef pair<ll,ll> pll;
29 const int INF=0x3f3f3f3f;
30 const ll INFF=0x3f3f3f3f3f3f3f3fll;
31 const int MAX=5e5+10;
32 //const ll MAXN=2e8;
33 //const int MAX_N=MAX;
34 const ll MOD=1e9+7;
35 //const long double pi=acos(-1.0);
36 //const double eps=0.00000001;
37 ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
38 template<typename T>inline T abs(T a) {return a>0?a:-a;}
39 template<class T> inline
40 void read(T& num) {
41     bool start=false,neg=false;
42     char c;
43     num=0;
44     while((c=getchar())!=EOF) {
45         if(c==-) start=neg=true;
46         else if(c>=0 && c<=9) {
47             start=true;
48             num=num*10+c-0;
49         } else if(start) break;
50     }
51     if(neg) num=-num;
52 }
53 inline ll powMM(ll a,ll b,ll M){
54     ll ret=1;
55     a%=M;
56 //    b%=M;
57     while (b){
58         if (b&1) ret=ret*a%M;
59         b>>=1;
60         a=a*a%M;
61     }
62     return ret;
63 }
64 void open()
65 {
66 //    freopen("1009.in","r",stdin);
67     freopen("out.txt","w",stdout);
68 }
69  
70 const int N = 2020;
71 ll C[N][N];
72 void init() {
73         for (int i = 0; i < N; i ++) C[i][0] = C[i][i] = 1;
74         for (int i = 1; i < N; i ++) {
75                 for (int j = 1; j < i; j ++) {
76                         C[i][j] = (C[i - 1][j] + C[i - 1][j - 1]) % MOD;
77                 }
78         }
79 }
80 int a,b;
81 ll an,lin;
82 int main()
83 {
84     init();
85     scanf("%d%d",&a,&b);
86     an=a+1;
87     for(int i=1;i<=min(a,b-1);i++)//第一次向下的位置的横坐标
88     {
89         for(int j=0;j<i&&j+i<=a;j++)
90         {
91             lin=C[b-1][i]*C[i-1][j]%MOD*C[a-i-j+2][2]%MOD;
92             an=(an+lin)%MOD;
93         }
94     }
95     printf("%lld\n",an);
96  
97 }
View Code

F

如果一个环由2部分构成(长度不一定相同,但同一部分的位置不能改变,且每一部分的任意前缀串s,其任意长度的后缀均比相同长度的前缀字典序”不小于”)设两部分分别为x\y

将其连接而成的一个环,只可能由这两部分的起始位置作为起点的串可能为Smallest Cyclic Shift(以下简写为SCS)因为取某部分的后缀作为开头,则其已经不小于该部分的前缀,如果是大于显然取前缀作为开头更优,如果是等于,最后比较的还是两部分的前缀。

而x、y比较得x字典序更小,故xy即为所求的字符串。

一般地,如果一个环由k部分构成(k>=3),易证在欲使最终的SCS最大的情况下,将k部分转化成k-1部分,一定是选择字典序最小的部分与字典序最大的部分相连。

最初有x+y+z个部分,分别是x个a,y个b,z个c,将其按上述操作反复进行即可。

技术分享
 1  #include <cstdio>
 2 #include <iostream>
 3 #include <algorithm>
 4 #include <vector>
 5 #include <set>
 6 #include <map>
 7 #include <string>
 8 #include <cstring>
 9 #include <stack>
10 #include <queue>
11 #include <cmath>
12 #include <ctime>
13 #include <bitset>
14 #include <utility>
15 #include <assert.h>
16 using namespace std;
17 #define rank rankk
18 #define mp make_pair
19 #define pb push_back
20 #define xo(a,b) ((b)&1?(a):0)
21 #define tm tmp
22 //#pragma comment(linker, "/STACK:1024000000,1024000000") 
23 //#define LL ll
24 typedef unsigned long long ull;
25 typedef pair<int,int> pii;
26 typedef long long ll;
27 typedef pair<ll,int> pli;
28 typedef pair<ll,ll> pll;
29 const int INF=0x3f3f3f3f;
30 const ll INFF=0x3f3f3f3f3f3f3f3fll;
31 const int MAX=5e5+10;
32 //const ll MAXN=2e8;
33 //const int MAX_N=MAX;
34 const ll MOD=1e9+7;
35 //const long double pi=acos(-1.0);
36 //const double eps=0.00000001;
37 ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
38 template<typename T>inline T abs(T a) {return a>0?a:-a;}
39 template<class T> inline
40 void read(T& num) {
41     bool start=false,neg=false;
42     char c;
43     num=0;
44     while((c=getchar())!=EOF) {
45         if(c==-) start=neg=true;
46         else if(c>=0 && c<=9) {
47             start=true;
48             num=num*10+c-0;
49         } else if(start) break;
50     }
51     if(neg) num=-num;
52 }
53 inline ll powMM(ll a,ll b,ll M){
54     ll ret=1;
55     a%=M;
56 //    b%=M;
57     while (b){
58         if (b&1) ret=ret*a%M;
59         b>>=1;
60         a=a*a%M;
61     }
62     return ret;
63 }
64 void open()
65 {
66 //    freopen("1009.in","r",stdin);
67     freopen("out.txt","w",stdout);
68 }
69 int x,y,z;
70 vector<string>s;
71 int main()
72 {
73     scanf("%d%d%d",&x,&y,&z);
74     for(int i=0;i<x;i++)s.pb("a");
75     for(int i=0;i<y;i++)s.pb("b");
76     for(int j=0;j<z;j++)s.pb("c");
77     while(s.size()>1)
78     {
79         sort(s.begin(),s.end());
80         s[0]+=s[s.size()-1];
81         s.pop_back();
82     }
83     cout<<s[0]<<"\n";
84 }
85 /*
86 8
87 11011011
88 */
View Code

 

以上是关于CODE FESTIVAL 2017 qual B 解题报告的主要内容,如果未能解决你的问题,请参考以下文章

CODE FESTIVAL 2017 qual B 解题报告

101 to 010 Atcoder CODE FESTIVAL 2017 qual B D

CODE FESTIVAL 2017 qual B B - Problem Set水体,stl map

[Atcoder Code Festival 2017 Qual B Problem F]Largest Smallest Cyclic Shift

CODE FESTIVAL 2017 qual A--B-fLIP(换种想法,暴力枚举)

CODE FESTIVAL 2017 qual A 题解