1. 程式人生 > >CODE FESTIVAL 2017 qual B 解題報告

CODE FESTIVAL 2017 qual B 解題報告

pop cnblogs min air 坐標 第一次 最大 com type

做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 解題報告