CODE FESTIVAL 2017 qual B 解題報告
做atcoder總是感到格外的智商不足……感覺atcoder比起codeforces來說題目普遍更有趣,更考驗思維orz
C
題意:給出無向圖,距離為3的點如果未連邊,則可以連上一條邊,問最多能連多少邊。
解題思路:
易證距離(可以非簡單路)為奇數的均可以連邊。
如果是二分圖,則圖中不存在奇環,最終狀態二分圖兩部的點彼此有連邊。
非二分圖的連通圖一定存在奇環,則任意兩點若初始距離非奇數,加上奇環之後距離就必可變為奇數。最終狀態為完全圖。
按最終狀態的邊數減去當下邊數即可。
1 #include <cstdio> 2 #include <iostream> 3View Code#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 longull; 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 }
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 解題報告