TC250专场
SRM 623 DIV2 1000pt
题意:给出一个最多50*50的矩阵,每个单元可能为'.'、'P'、'A','.'代表空地,你每次操作可以把一个P或者A拿到空地上,求一个最大的含有相同字符的矩形面积,最多K次操作。
首先用一个数组预处理出所有矩形所包含这三种字符的数量,然后枚举每一个矩形,如果只含有相同字符,那么这个面积是可以取到的。
如果含有多种字符,枚举含哪种字符时所需操作最少,大矩阵内如果含有一个及以上空地并且这个矩形的面积是小于等于你当前枚举的字符的数量,操作数=矩形内空地数+令一字符数*2
1 #include <iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<stdlib.h> 6 #include<vector> 7 #include<cmath> 8 #include<queue> 9 #include<set> 10 using namespace std; 11 #define N 100000 12 #define LL long long 13 #define INF 0xfffffff 14 const double eps = 1e-8; 15 const double pi = acos(-1.0); 16 const double inf = ~0u>>2; 17 18 int s[65][65][3]; 19 class ApplesAndPears 20 { 21 public: 22 int getArea(vector <string> board, int K) 23 { 24 int n = board.size(); 25 int m = board[0].size(); 26 int i,j,g,e; 27 memset(s,0,sizeof(s)); 28 int a = 0,b = 0,c = 0; 29 for(i = 0; i < n ; i++) 30 for(j = 0; j < m; j++) 31 { 32 s[i+1][j+1][0] = s[i][j+1][0]+s[i+1][j][0]-s[i][j][0]; 33 s[i+1][j+1][1] = s[i][j+1][1]+s[i+1][j][1]-s[i][j][1]; 34 s[i+1][j+1][2] = s[i][j+1][2]+s[i+1][j][2]-s[i][j][2]; 35 if(board[i][j]=='.') 36 { 37 a++; 38 s[i+1][j+1][0]+=1; 39 } 40 else if(board[i][j]=='A') 41 { 42 b++; 43 s[i+1][j+1][1]+=1; 44 } 45 else 46 { 47 c++; 48 s[i+1][j+1][2]+=1; 49 } 50 } 51 int ans = 0; 52 for(i = 1 ; i <= n ; i++) 53 { 54 for(j = 1 ; j <= m ; j++) 55 { 56 for(g = 1 ; g <= i ; g++) 57 for(e = 1; e <= j ; e++) 58 { 59 int k1 = s[i][j][0]-s[g-1][j][0]-s[i][e-1][0]+s[g-1][e-1][0]; 60 int k2 = s[i][j][1]-s[g-1][j][1]-s[i][e-1][1]+s[g-1][e-1][1]; 61 int k3 = s[i][j][2]-s[g-1][j][2]-s[i][e-1][2]+s[g-1][e-1][2]; 62 63 int area = (i-g+1)*(j-e+1); 64 int res1 = area-k1; 65 if(k1==area||k2==area||k3==area) 66 { 67 ans = max(area,ans); 68 continue; 69 } 70 if(area<=a&&K>=res1) ans = max(ans,area); 71 res1 = area-k2; 72 int res2 = res1-k1; 73 if(area<=b&&a&&res2+res1<=K) ans = max(ans,area); 74 res1 = area-k3; 75 res2 = res1-k1; 76 if(area<=c&&a&&res2+res1<=K) ans = max(ans,area); 77 } 78 } 79 } 80 return ans; 81 } 82 };
SRM 631 DIV1 250
题意:给你一个n*n的网格,n为偶数,上面有白的还有黑的,如果由一列超过n/2个连续相同的颜色,这个网格将是不好的,你可以一次将一行染成白或黑,问最少的操作次数。
做法:因为需要超过n/2才是不好的,所以最多2次染色就可以了,n/2-1行全染白,n/2+1行全染黑,这样肯定是好网格,本就是好的返回0,所以枚举染1次的时候能不能把它变好即可。
1 #include <iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<stdlib.h> 6 #include<vector> 7 #include<cmath> 8 #include<queue> 9 #include<set> 10 using namespace std; 11 #define N 100 12 #define LL long long 13 #define INF 0xfffffff 14 const double eps = 1e-8; 15 const double pi = acos(-1.0); 16 const double inf = ~0u>>2; 17 char str[N][N],st[N][N]; 18 int judge(char grid[][100],int n) 19 { 20 int i,j; 21 for(i = 0 ; i < n ; i++) 22 { 23 int ts = 1,ss=1; 24 for(j = 1; j < n ; j++) 25 if(grid[j][i]==grid[j-1][i]) 26 { 27 ts++; 28 ss = max(ss,ts); 29 } 30 else ts=1; 31 if(ss>n/2) return 1; 32 } 33 return 0; 34 } 35 int solve(int k,char f,char grid[][100],int n) 36 { 37 int i,j; 38 for(i = 0 ; i < n; i++) 39 for(j = 0 ;j < n; j++) 40 str[i][j] = grid[i][j]; 41 for(j = 0 ; j < n; j++) 42 str[k][j] = f; 43 if(judge(str,n)==0) return 1; 44 return 0; 45 } 46 class TaroJiroGrid 47 { 48 public: 49 int getNumber(vector <string> grid) 50 { 51 int n = grid.size(),i,j; 52 for(i = 0 ;i < n; i++) 53 for(j = 0 ;j < n; j++) 54 st[i][j] = grid[i][j]; 55 if(judge(str,n)==0) return 0; 56 for(i = 0 ;i < n; i++) 57 { 58 if(solve(i,'W',str,n)==0||solve(i,'B',str,n)==0) return 1; 59 } 60 61 return 2; 62 } 63 };
SRM 630 DIV1 250
题意:有N个城市,n-1条路把这n个城市连接起来,每条路由一个权值,求一个最大的集合满足集合中任意两个城市的距离为d
做法:dfs
1 #include <iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<stdlib.h> 6 #include<vector> 7 #include<cmath> 8 #include<queue> 9 #include<set> 10 using namespace std; 11 #define N 55 12 #define LL long long 13 #define INF 0xfffffff 14 const double eps = 1e-8; 15 const double pi = acos(-1.0); 16 const double inf = ~0u>>2; 17 vector<int>ed[N]; 18 int w[N][N]; 19 int o[N]; 20 int maxz; 21 int m; 22 bool vis[N]; 23 void dfs(int u,int d,int num) 24 { 25 int i,j; 26 o[num] = u; 27 maxz = max(num+1,maxz); 28 if(u==m+1) return ; 29 if(num+1+m-u<=maxz) return ; 30 for(i = u+1 ; i <= m ; i++) 31 { 32 int v = i; 33 if(d!=-1&&w[u][v]!=d) continue; 34 35 int flag = 1; 36 for(j = 0; j < num ; j++) 37 if(w[o[j]][v]!=w[u][v]){flag=0; break;} 38 if(flag) 39 dfs(v,w[u][v],num+1); 40 } 41 } 42 class Egalitarianism3 43 { 44 public: 45 int maxCities(int n, vector <int> a, vector <int> b, vector <int> len) 46 { 47 int k = a.size(),i,j; 48 m = n; 49 if(n==1) return 1; 50 for(i = 1 ; i <=n; i++) 51 { 52 for(j = 1 ; j <= n; j++) 53 w[i][j] = INF; 54 w[i][i] = 0; 55 } 56 for(i = 0 ; i < k; i++) 57 w[a[i]][b[i]] = w[b[i]][a[i]] = len[i]; 58 for(i = 1; i <= n; i++) 59 for(j = 1; j<= n; j++) 60 for(k = 1; k <= n ; k++) 61 w[j][k] = min(w[j][i]+w[i][k],w[j][k]); 62 for(i = 1 ;i <= n; i++) 63 dfs(i,-1,0); 64 return maxz; 65 } 66 };
SRM 629 DIV1 250
题意:有一个w*h的矩形洞,给你很多板子以及板子的长和宽,求最少的需要的板子把洞覆盖住。
1 #include <iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<stdlib.h> 6 #include<vector> 7 #include<cmath> 8 #include<queue> 9 #include<set> 10 using namespace std; 11 #define N 100000 12 #define LL long long 13 #define INF 0xfffffff 14 const double eps = 1e-8; 15 const double pi = acos(-1.0); 16 const double inf = ~0u>>2; 17 int a[N]; 18 class RectangleCovering 19 { 20 public: 21 int minimumNumber(int holeH, int holeW, vector <int> boardH, vector <int> boardW) 22 { 23 int i,k = boardH.size(); 24 for(i = 0 ; i < k ; i++) 25 { 26 if(boardH[i]>holeH&&boardW[i]>holeH) 27 a[i] = max(boardH[i],boardW[i]); 28 else if(boardH[i]>holeH) 29 a[i] = boardW[i]; 30 else if(boardW[i]>holeH) 31 a[i] = boardH[i]; 32 else a[i] = 0; 33 } 34 sort(a,a+k); 35 int ans = INF; 36 int cnt = 0,sum = 0; 37 for(i = k-1 ; i >= 0 ; i--) 38 { 39 if(a[i]==0) break; 40 cnt++; 41 sum+=a[i]; 42 if(sum>=holeW) 43 { 44 ans = min(ans,cnt); 45 } 46 } 47 int t; 48 t = holeH; 49 holeH = holeW; 50 holeW = t; 51 for(i = 0 ; i < k ; i++) 52 { 53 if(boardH[i]>holeH&&boardW[i]>holeH) 54 a[i] = max(boardH[i],boardW[i]); 55 else if(boardH[i]>holeH) 56 a[i] = boardW[i]; 57 else if(boardW[i]>holeH) 58 a[i] = boardH[i]; 59 else a[i] = 0; 60 } 61 sort(a,a+k); 62 cnt = 0,sum = 0; 63 64 for(i = k-1 ; i >= 0 ; i--) 65 { 66 if(a[i]==0) break; 67 cnt++; 68 sum+=a[i]; 69 if(sum>=holeW) 70 { 71 ans = min(ans,cnt); 72 } 73 } 74 if(ans!=INF) return ans; 75 return -1; 76 } 77 }; 78 int main() 79 { 80 81 return 0; 82 }
SRM 628 DIV1 250
题意:给出一个n,让你求出一个最小的x,使得x^(x的约数的个数)=n
做法:枚举开n的多次幂,最多开到64.注意一个非1对的数的约数至少为2.。
1 #include <iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<stdlib.h> 6 #include<vector> 7 #include<cmath> 8 #include<queue> 9 #include<set> 10 #include<ctime> 11 using namespace std; 12 #define N 100000 13 #define LL long long 14 #define INF 0xfffffff 15 const double eps = 1e-8; 16 const double pi = acos(-1.0); 17 const double inf = ~0u>>2; 18 const int S = 20; 19 LL poww(LL a,int n) 20 { 21 LL t; 22 if(n==0) return 1; 23 if(n==1) return a; 24 t=poww(a,n/2); 25 t=t*t; 26 if((n&1)==1) t=t*a; 27 return t; 28 } 29 int judge(LL x,int k) 30 { 31 int i; 32 int s = 1; 33 int ans = 1; 34 if(x==2) return k==2; 35 if(x==1) return k==1; 36 for(i = 2; i*i<=x ; i++) 37 { 38 if(x%i==0) 39 { 40 s = 0; 41 while(x%i==0) 42 { 43 x/=i; 44 s++; 45 } 46 ans*=(s+1); 47 } 48 if(ans>k) return 0; 49 } 50 if(x!=1) ans*=2; 51 if(ans==k) return 1; 52 return 0; 53 } 54 //int check(LL k,LL n,int i) 55 //{ 56 // LL s = poww(k,i); 57 // if(s!=n) return 0; 58 // 59 // return 1; 60 //} 61 class DivisorsPower 62 { 63 public: 64 long findArgument(long n) 65 { 66 int i; 67 LL k; 68 for(i= 64 ; i >= 2 ; i--) 69 { 70 double a = pow(n*1.0,1.0/i); 71 k = round(a); 72 LL s = poww(k,i); 73 if(s!=n) continue; 74 if(judge(k,i)) 75 { 76 return k; 77 } 78 } 79 return -1; 80 } 81 }; 82 int main() 83 { 84 85 return 0; 86 }
SRM 627 DIV1 250
题意:给出一个字符串,两个不一样的字母可以同时消掉,问消到最后有哪些字母可能会留下。
做法:统计出每个字母的个数,枚举当前字母,若当前字母可以留下,则其它所有字母数量都需满足num[j]>sum-num[j]。
1 #include <iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<stdlib.h> 6 #include<vector> 7 #include<cmath> 8 #include<queue> 9 #include<set> 10 using namespace std; 11 #define N 111 12 #define LL long long 13 #define INF 0xfffffff 14 const double eps = 1e-8; 15 const double pi = acos(-1.0); 16 const double inf = ~0u>>2; 17 vector<int>q; 18 int num[30]; 19 string s; 20 class HappyLetterDiv1 21 { 22 public: 23 string getHappyLetters(string letters) 24 { 25 int n = letters.length(); 26 int sum = 0,i,j; 27 for(i = 0 ; i < n; i++) 28 { 29 int d = letters[i]-'a'; 30 sum+=d; 31 num[d]++; 32 } 33 for(i = 0; i < 26 ; i++) 34 { 35 if(!num[i]) continue; 36 if((num[i]==1&&sum%2==0)) 37 { 38 continue; 39 } 40 int tsum = sum,ff=1; 41 if(sum%2) tsum-=1; 42 else tsum -= 2; 43 for(j = 0 ; j < 26 ; j++) 44 if(i==j) continue; 45 else 46 { 47 if(num[j]>tsum) 48 { 49 ff = 0; 50 break; 51 } 52 } 53 if(ff) s+=(i+'a'); 54 } 55 return s; 56 } 57 58 }; 59 60 int main() 61 { 62 63 return 0; 64 }
SRM 626 DIV1 250
题意:两人在玩骰子,小A玩a个b面的,小B玩c个d面的,问小A赢得期望。
做法:求出所有小A赢的可能性,用总分/所有的可能
1 #include <iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<stdlib.h> 6 #include<vector> 7 #include<cmath> 8 #include<queue> 9 #include<set> 10 using namespace std; 11 #define N 55 12 #define LL long long 13 #define INF 0xfffffff 14 const double eps = 1e-8; 15 const double pi = acos(-1.0); 16 const double inf = ~0u>>2; 17 double dp1[N][N*N],dp2[N][N*N]; 18 class FixedDiceGameDiv1 19 { 20 public: 21 double getExpectation(int a, int b, int c, int d) 22 { 23 int i,j,g; 24 if(a*b<=c) return -1; 25 for(i = 1; i <= b; i++) 26 dp1[1][i] = 1.0/b; 27 for(i = 1; i <= d; i ++) 28 dp2[1][i] = 1.0/d; 29 for(i = 2;i <= a ; i++) 30 for(j = i ; j <= i*b ; j++) 31 { 32 for(g = 1; g <= b; g++) 33 if(j<=g) continue; 34 else 35 dp1[i][j] += dp1[i-1][j-g]/b; 36 } 37 for(i = 1; i <= d; i++) 38 dp2[1][i] = 1; 39 for(i = 2;i <= c ; i++) 40 for(j = i ; j <= i*d ; j++) 41 { 42 for(g = 1; g <= d; g++) 43 if(j<=g) continue; 44 else 45 dp2[i][j] += dp2[i-1][j-g]/d; 46 } 47 double ans = 0; 48 double o =0 ; 49 for(i = 2; i <= a*b ; i++) 50 { 51 if(!dp1[a][i]) continue; 52 for(j = 1 ; j < i; j++) 53 if(dp2[c][j]) 54 { 55 o+=dp1[a][i]*dp2[c][j]; 56 ans+=i*1.0*dp1[a][i]*dp2[c][j]; 57 } 58 } 59 return ans/o; 60 } 61 };
SRM 625 DIV1 250
题意:给你一个字符串,让你求出子串为回文串的可能性。
做法:组合的问题,如果是回文串的话,只有两种形式,奇数的 和偶数的,分情况讨论,分界点两边的各字母个数相同。
1 #include <iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<stdlib.h> 6 #include<vector> 7 #include<cmath> 8 #include<queue> 9 #include<set> 10 using namespace std; 11 #define N 100000 12 #define LL long long 13 #define INF 0xfffffff 14 const double eps = 1e-8; 15 const double pi = acos(-1.0); 16 const double inf = ~0u>>2; 17 int o[30]; 18 LL num[30]; 19 LL cal(int x) 20 { 21 int i; 22 LL s = 1; 23 for(i = 1; i <= x; i++) 24 s*=i; 25 return s; 26 } 27 class PalindromePermutations 28 { 29 public: 30 double palindromeProbability(string word) 31 { 32 int k = word.length(),i,j; 33 double s = 1.0; 34 for(i =0 ; i < k; i++) 35 o[word[i]-'a']++; 36 if(k%2==0) 37 { 38 for(i = 0 ; i < 26 ; i++) 39 { 40 if(o[i]%2) return 0; 41 } 42 for(i = 0 ; i< 26 ; i++) 43 { 44 if(!o[i]) continue; 45 for(j = o[i]/2+1 ; j <= o[i] ; j++) 46 s*=j; 47 } 48 for(i = k/2+1 ; i <= k; i++) 49 { 50 s/=i; 51 } 52 } 53 else 54 { 55 double x=-1; 56 for(i = 0 ; i < 26 ; i++) 57 { 58 if(o[i]%2) 59 { 60 if(x!=-1) return 0; 61 x = i; 62 } 63 } 64 for(i = 0 ; i< 26 ; i++) 65 { 66 if(!o[i]) continue; 67 for(j = o[i]/2+1 ; j <= o[i] ; j++) 68 s*=j; 69 } 70 for(i = k/2+1 ; i <= k; i++) 71 { 72 s/=i; 73 } 74 } 75 return s; 76 } 77 };
SRM 624 DIV1 250
题意:从左到右有很多高楼,给出他们的高度,问至少有i个高度相同的建筑物需要最少提升多少高度,把这些异或起来。
做法:枚举提升j个与第i个高楼一样高度时候所需要的最小花费,排序即可。
1 #include <iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<stdlib.h> 6 #include<vector> 7 #include<cmath> 8 #include<queue> 9 #include<set> 10 using namespace std; 11 #define N 4010 12 #define LL long long 13 #define INF 0xfffffff 14 const double eps = 1e-8; 15 const double pi = acos(-1.0); 16 const double inf = ~0u>>2; 17 int num[N][N],p,a[N]; 18 bool cmp(int a,int b) 19 { 20 return p-a<p-b; 21 } 22 class BuildingHeights 23 { 24 public: 25 26 int minimum(vector <int> heights) 27 { 28 int i,j,k = heights.size(); 29 for(i = 0 ; i < k; i++) 30 a[i] = heights[i]; 31 sort(a,a+k); 32 for(i = 0 ; i < k; i++) 33 { 34 p = heights[i]; 35 sort(a,a+k,cmp); 36 int g = 0; 37 for(j = 0; j < k ; j++) 38 if(a[j]>p) {continue;} 39 else 40 { 41 num[i][g+1] = num[i][g]+p-a[j]; 42 g++; 43 } 44 cout<<p<<endl; 45 for(j = g+1 ; j <= k; j++) 46 num[i][j] = INF; 47 } 48 int ans = 0; 49 for(i = 1 ; i <= k ; i++) 50 { 51 int ts = INF; 52 for(j = 0 ; j < k ; j++) 53 ts = min(ts,num[j][i]); 54 cout<<ts<<endl; 55 ans^=ts; 56 } 57 return ans; 58 } 59 };
SRM 623 DIV1 250
题意:有一个n*m的矩阵里面种着梨和苹果还有空地,一次只能操作一个原有东西将其放在空地上,不能移除,问在k次操作内能得到的最大的一个只包含苹果的矩阵。
做法:枚举这个矩阵。
1 #include <iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<stdlib.h> 6 #include<vector> 7 #include<cmath> 8 #include<queue> 9 #include<set> 10 using namespace std; 11 #define N 4010 12 #define LL long long 13 #define INF 0xfffffff 14 const double eps = 1e-8; 15 const double pi = acos(-1.0); 16 const double inf = ~0u>>2; 17 18 class UniformBoard 19 { 20 public: 21 22 int getBoard(vector <string> board, int K) 23 { 24 int n = board[0].size(); 25 int p = 0,a =0 ,d = 0,i,j,x,y,g,e; 26 for(i = 0 ; i< n; i++) 27 for(j =0 ; j < n; j++) 28 if(board[i][j]=='P') 29 p++; 30 else if(board[i][j]=='A') a++; 31 else d++; 32 int ans = 0; 33 for(i = 0; i < n ; i++) 34 for(j = 0; j < n; j++) 35 { 36 for(x = i ; x < n; x++) 37 for(y = j ; y < n; y++) 38 { 39 int ta=0,td=0,tp = 0; 40 for(g = i ; g <= x ; g++) 41 for(e = j ; e <= y ; e++) 42 if(board[g][e]=='P') tp++; 43 else if(board[g][e]=='A') ta++; 44 else td++; 45 int sum = (x-i+1)*(y-j+1); 46 if(a<sum) continue; 47 if(ta==sum) {ans = max(ans,sum);continue;} 48 else 49 { 50 if(d==0) continue; 51 int o = tp+sum-ta; 52 // if(i==2&&x==2&&j==0&&y==2) 53 // cout<<o<<endl; 54 if(K<o) continue; 55 ans = max(ans,sum); 56 } 57 } 58 } 59 return ans; 60 } 61 };
SRM 620 DIV1 250
题意:对于(x,y)可以变为(x+y,y)和(x,x+y),给你abcd,问是否存在(x,y)可以变为(a,b) 和(c,d) 返回最大x+y的(x,y);
做法:暴力枚举a,b的前N步,vector[x]存y,在cd中二分查找是否出现过y
1 #include <iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<stdlib.h> 6 #include<vector> 7 #include<cmath> 8 #include<queue> 9 #include<set> 10 using namespace std; 11 #define N 1000010 12 #define LL long long 13 #define INF 0xfffffff 14 const double eps = 1e-8; 15 const double pi = acos(-1.0); 16 const double inf = ~0u>>2; 17 vector<int>ed[N]; 18 int o[N]; 19 class PairGame 20 { 21 public: 22 int maxSum(int a, int b, int c, int d) 23 { 24 if(a==c&&b==d) return a+b; 25 ed[a].push_back(b); 26 o[0] = a; 27 int g = 1,i; 28 while(a!=b) 29 { 30 if(b>a) 31 b=b-a; 32 else 33 { 34 a = a-b; o[g++] = a; 35 } 36 ed[a].push_back(b); 37 } 38 for(i = 0 ; i < g; i++) 39 sort(ed[o[i]].begin(),ed[o[i]].end()); 40 vector<int>::iterator it; 41 it = lower_bound(ed[c].begin(),ed[c].end(),d); 42 for(i = 0 ; i < ed[c].size() ; i++) 43 cout<<ed[c][i]<<" "; 44 puts(""); 45 if(it!=ed[c].end()&&*it==d) 46 { 47 return c+d; 48 } 49 while(c!=d) 50 { 51 if(d>c) 52 d=d-c; 53 else c = c-d; 54 //cout<<c<<" "<<d<<endl; 55 it = lower_bound(ed[c].begin(),ed[c].end(),d); 56 if(it!=ed[c].end()&&*it==d) 57 { 58 return c+d; 59 } 60 } 61 return -1; 62 } 63 };
SRM 619 DIV1 250
题意:有n堆石头,每堆石头有A[i]个小石头,两人在玩游戏,每次将一堆分成两堆放在剩余的其它两堆上面,谁最后无法操作就输了。
做法:判断奇偶性,(n-2)%2为奇数先手赢,经过分类讨论1的个数,发现与1的 个数无关。
1 #include <iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<stdlib.h> 6 #include<vector> 7 #include<cmath> 8 #include<queue> 9 #include<set> 10 using namespace std; 11 #define N 100000 12 #define LL long long 13 #define INF 0xfffffff 14 const double eps = 1e-8; 15 const double pi = acos(-1.0); 16 const double inf = ~0u>>2; 17 class SplitStoneGame 18 { 19 public: 20 string winOrLose(vector <int> number) 21 { 22 int n = number.size(); 23 int a = 0,b=0,i; 24 for(i = 0 ; i < n; i++) 25 if(number[i]==1) 26 a++; 27 b = n-a; 28 if(n<3||b==0) return "LOSE"; 29 if(n%2) return "WIN"; 30 else return "LOSE"; 31 } 32 };
SRM 618 DIV1 250
题意:以前做的,记不清了。。
做法:图的染色问题
1 #include <iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<stdlib.h> 6 #include<vector> 7 #include<cmath> 8 #include<queue> 9 #include<set> 10 using namespace std; 11 #define N 100000 12 #define LL long long 13 #define INF 0xfffffff 14 const double eps = 1e-8; 15 const double pi = acos(-1.0); 16 const double inf = ~0u>>2; 17 vector<int>f[110]; 18 int flag; 19 int vis[110]; 20 void dfs(int u,int c) 21 { 22 int i; 23 if(flag) return ; 24 vis[u] = c; 25 for(i = 0 ; i < (int)f[u].size() ; i++) 26 { 27 int v = f[u][i]; 28 if(!vis[v]) 29 dfs(v,-c); 30 else if(vis[v]!=-c) 31 { 32 flag = 1; 33 break; 34 } 35 } 36 } 37 class Family 38 { 39 public: 40 string isFamily(vector <int> parent1, vector <int> parent2) 41 { 42 int k = parent1.size(); 43 int i; 44 for(i = 0 ;i < k ; i++) 45 { 46 int u1 = parent1[i],u2 =parent2[i] ; 47 if(u1==u2) 48 { 49 if(u2!=-1) 50 { 51 flag = 1; 52 break; 53 } 54 } 55 else if(u1==-1||u2==-1) 56 { 57 flag = 1; 58 break; 59 } 60 else if(u1>=i||u2>=i) 61 { 62 flag = 1; 63 break; 64 } 65 else 66 { 67 f[u1].push_back(u2); 68 f[u2].push_back(u1); 69 } 70 } 71 for(i = 0 ;i < k ;i++) 72 { 73 if(!vis[i]) 74 dfs(i,1); 75 if(flag) break; 76 } 77 if(flag) 78 return "Impossible"; 79 else 80 return "Possible"; 81 } 82 83 };
SRM 616 DIV1 250
题意:一个人在睡觉,他有一个睡眠指数k,当k<=0时他会醒,他旁边有n个闹钟,每一个每隔一段时间会响,会使k减少,k值每分钟会增加d,问初始k值最大为多少时,他会在某个时刻醒。
做法:取每个闹钟的周期的LCM,以LCM枚举时间。
1 #include <iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<stdlib.h> 6 #include<vector> 7 #include<cmath> 8 #include<queue> 9 #include<set> 10 using namespace std; 11 #define N 10000000 12 #define LL long long 13 #define INF 0xfffffff 14 const double eps = 1e-8; 15 const double pi = acos(-1.0); 16 const double inf = ~0u>>2; 17 bool o[N]; 18 class 19 WakingUp 20 { 21 public: 22 int maxSleepiness(vector <int> period, vector <int> start, vector <int> volume, int D) 23 { 24 int n = period.size(),i; 25 26 int t = 1 ,tt=1; 27 for(i = 1 ; i <= 10 ; i++) 28 tt = i*tt/__gcd(i,tt); 29 int td = 0; 30 int ans = 0; 31 while(t<=tt) 32 { 33 td+=D; 34 for(i = 0; i < n; i++) 35 { 36 if(t>=start[i]&&(t-start[i])%period[i]==0) 37 td-=volume[i]; 38 } 39 ans = max(ans,-td); 40 t++; 41 } 42 if(td<0) return -1; 43 return ans; 44 } 45 };
SRM 615 DIV1 250
题意:顺序给你一些数,有一个变形虫,初始体积不知道,当他遇到与它体积一样的数他就会扩大一倍,问有哪些数不是他最后可能的体积。
做法:枚举他初始的体积,依次向后走,途中的体积不可达,加入set中,走到最后会得到一个体积,抹除这个数。
1 #include <iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<stdlib.h> 6 #include<vector> 7 #include<cmath> 8 #include<queue> 9 #include<set> 10 #include<map> 11 using namespace std; 12 #define N 100000 13 #define LL long long 14 #define INF 0xfffffff 15 const double eps = 1e-8; 16 const double pi = acos(-1.0); 17 const double inf = ~0u>>2; 18 #define all(o) (o).begin(),(o).end() 19 class AmebaDiv1 20 { 21 public: 22 int count(vector <int> X) 23 { 24 int n = X.size(),i,j; 25 set<int>s(all(X)); 26 for(i = 0 ; i< n; i++) 27 { 28 int x = X[i]; 29 for(j =0 ; j< n; j++) 30 { 31 if(x==X[j]) x*=2; 32 } 33 s.erase(x); 34 } 35 return s.size(); 36 } 37 };
SRM 614 DIV1 250
题意:有一个二维坐标平面,上面有些点,让你画出一个平行于坐标轴并且顶点为整数坐标的正方形圈住最少K个点,返回满足条件的最小正方形面积。
做法: 枚举正方形最左、最下、最右的点和最左、最上、最下的点。
1 #include <iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<stdlib.h> 6 #include<vector> 7 #include<cmath> 8 #include<queue> 9 #include<set> 10 using namespace std; 11 #define N 105 12 #define LL long long 13 14 const double eps = 1e-8; 15 const double pi = acos(-1.0); 16 const double inf = ~0u>>2; 17 vector<int>tx; 18 struct point 19 { 20 int x,y; 21 point(int x=0,int y=0):x(x),y(y){} 22 }p[N]; 23 24 bool cmp(point a,point b) 25 { 26 if(a.y==b.y) return a.x<b.x; 27 return a.y<b.y; 28 } 29 30 class MinimumSquare 31 { 32 public: 33 long long minArea(vector <int> x, vector <int> y, int K) 34 { 35 int n = x.size(),i,j,g,e; 36 for(i = 0; i < n; i++) 37 { 38 p[i] = point(x[i],y[i]); 39 } 40 LL ans = 4000000008000000007LL; 41 for(i = 0 ; i < n; i++) 42 { 43 for(j = 0 ; j < n; j++) 44 { 45 if(p[j].x<p[i].x) continue; 46 if(p[j].y>p[i].y) continue; 47 for(g = 0; g < n; g++) 48 { 49 if(p[g].x<p[j].x) continue; 50 if(p[g].y<p[j].y) continue; 51 int tn = 0; 52 LL len = max(p[g].x-p[i].x+2,max(p[g].y-p[j].y+2,p[i].y-p[j].y+2)); 53 for(e = 0 ; e < n; e++) 54 { 55 if(p[e].y<p[j].y) continue; 56 if(p[e].x<p[i].x) continue; 57 if(p[e].y-p[j].y+2<=len&&p[e].x-p[i].x+2<=len) 58 tn++; 59 } 60 if(tn<K) continue; 61 ans = min(len*len,ans); 62 } 63 for(g = 0; g < n; g++) 64 { 65 if(p[g].x<p[i].x) continue; 66 if(p[g].y<p[i].y) continue; 67 int tn = 0; 68 LL len = max(p[g].y-p[j].y+2,max(p[g].x-p[i].x+2,p[j].x-p[i].x+2)); 69 for(e = 0 ; e < n; e++) 70 { 71 if(p[e].y<p[j].y) continue; 72 if(p[e].x<p[i].x) continue; 73 if(p[e].y-p[j].y+2<=len&&p[e].x-p[i].x+2<=len) 74 tn++; 75 } 76 if(tn<K) continue; 77 ans = min(len*len,ans); 78 } 79 } 80 } 81 return ans; 82 } 83 };
SRM 613 DIV1 250
题意:X轴上有一些点,他们可以向左或者向右移动X,求min(R-L)。
做法:枚举以哪个点为轴进行其他点的移动。
1 #include <iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<stdlib.h> 6 #include<vector> 7 #include<cmath> 8 #include<queue> 9 #include<set> 10 using namespace std; 11 #define N 100000 12 #define LL long long 13 #define INF (2*1e9) 14 const double eps = 1e-8; 15 const double pi = acos(-1.0); 16 const double inf = ~0u>>2; 17 vector<int>co; 18 class TaroFriends 19 { 20 public: 21 int getNumber(vector <int> coordinates, int X) 22 { 23 int n = coordinates.size(); 24 int ans = INF,i,j; 25 sort(coordinates.begin(),coordinates.end()); 26 for(i = 0 ;i < n; i++) 27 { 28 co.clear(); 29 int x = coordinates[i]+X; 30 co.push_back(x); 31 for(j = 0 ;j < n ; j++) 32 if(j<i) co.push_back(coordinates[j]+X); 33 else if(j>i) co.push_back(coordinates[j]-X); 34 sort(co.begin(),co.end()); 35 ans= min(ans,co.back()-co[0]); 36 co.clear(); 37 x = coordinates[i]-X; 38 co.push_back(x); 39 for(j = 0 ;j < n ; j++) 40 if(j<i) co.push_back(coordinates[j]+X); 41 else if(j>i) co.push_back(coordinates[j]-X); 42 sort(co.begin(),co.end()); 43 ans= min(ans,co.back()-co[0]); 44 } 45 return ans; 46 } 47 };
SRM 612 DIV1 250
题意:聊天框里有一个字符,你需要打出k个字符,而且你只能做三种操作,复制当前框里所有字符,粘贴,或者删除一个字符,每秒只能操作一次,问最少的操作。
做法:dp,dp[i] = min(dp[i],dp[j]+1+粘贴次数-删除部分)。
1 #include <iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<stdlib.h> 6 #include<vector> 7 #include<cmath> 8 #include<queue> 9 #include<set> 10 using namespace std; 11 #define N 1010 12 #define LL long long 13 #define INF 0xfffffff 14 const double eps = 1e-8; 15 const double pi = acos(-1.0); 16 const double inf = ~0u>>2; 17 int dp[N]; 18 class 19 EmoticonsDiv1 20 { 21 public: 22 int printSmiles(int smiles) 23 { 24 int n = smiles,i,j; 25 dp[1] = 0; 26 for(i = 2; i <= n; i++) 27 { 28 dp[i] = INF; 29 for(j = 1 ; j < i ; j++) 30 { 31 int k = i/j; 32 if(i%j) k++; 33 dp[i] = min(dp[i],dp[j]+k+k*j-i); 34 } 35 cout<<i<<" "<<dp[i]<<endl; 36 } 37 return dp[n]; 38 } 39 40 };
SRM 611 DIV1 250
题意:给你一个字符串是不是符合这样的条件,一个数字k要么没出现,要么只出现两次并且前后相隔k个数字。
做法:保存位置,判断即可。
1 #include <iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<stdlib.h> 6 #include<vector> 7 #include<cmath> 8 #include<queue> 9 #include<set> 10 using namespace std; 11 #define N 1010 12 #define LL long long 13 #define INF 0xfffffff 14 const double eps = 1e-8; 15 const double pi = acos(-1.0); 16 const double inf = ~0u>>2; 17 int dp[N]; 18 vector<int>num[10]; 19 class 20 InterestingNumber 21 { 22 public: 23 string isInteresting(string x) 24 { 25 int i,j,n = x.length(); 26 for(i = 0 ; i < n; i++) 27 { 28 num[x[i]-'0'].push_back(i); 29 } 30 for(i = 0 ; i <= 9 ; i++) 31 { 32 if(num[i].size()==0) continue; 33 if(num[i].size()!=2) return "Not interesting"; 34 for(j = 1 ; j < num[i].size() ; j++) 35 if(num[i][j]-num[i][j-1]-1!=i) return "Not interesting"; 36 } 37 return "Interesting"; 38 } 39 40 };
SRM 610 DIV1 250
题意:给出一个01矩阵,找出最大的01混合的矩形。
做法:枚举以i,j为左下角的符合条件的矩形,x往右走,y往上走,边走边更新ans.
1 #include <iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<stdlib.h> 6 #include<vector> 7 #include<cmath> 8 #include<queue> 9 #include<set> 10 using namespace std; 11 #define N 1010 12 #define LL long long 13 #define INF 0xfffffff 14 const double eps = 1e-8; 15 const double pi = acos(-1.0); 16 const double inf = ~0u>>2; 17 int dp[N]; 18 vector<int>num[10]; 19 class 20 TheMatrix 21 { 22 public: 23 int MaxArea(vector <string> board) 24 { 25 int n = board.size(),i,j,g,e,m = board[0].size(); 26 int ans = 1; 27 for(i = 0; i < n; i++) 28 for(j = 0; j <m ; j++) 29 { 30 int x = 1,y=1; 31 for(g = i-1 ; g >= 0; g--) 32 if(board[g+1][j]==board[g][j]) break; 33 else y = i-g+1; 34 ans =max(ans,x*y); 35 for(g = j+1; g < m ; g++) 36 { 37 if(board[i][g]==board[i][g-1]) break; 38 x = g-j+1; 39 if(i==0) continue; 40 int ty = 1; 41 for(e = i-1 ; e >= 0 ; e--) 42 { 43 if(board[e][g]==board[e+1][g]) break; 44 ty = i-e+1; 45 } 46 y = min(ty,y); 47 ans = max(ans,x*y); 48 } 49 ans = max(ans,x*y); 50 } 51 return ans; 52 } 53 54 };
SRM 609 DIV1 250
题意:给你一个由‘<’和'>'组成的字符串,每一个操作可以删除一个字符,问最少操作得到的字符串 ,需符合>><<这种形式,前面k个>后面k个<,返回得到的字符串的长度。
做法:枚举哪个位置为最后字符串的第一个'<'。
1 #include <iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<stdlib.h> 6 #include<vector> 7 #include<cmath> 8 #include<queue> 9 #include<set> 10 using namespace std; 11 #define N 100000 12 #define LL long long 13 #define INF 0xfffffff 14 const double eps = 1e-8; 15 const double pi = acos(-1.0); 16 const double inf = ~0u>>2; 17 class 18 MagicalStringDiv1 19 { 20 public: 21 int getLongest(string S) 22 { 23 int n = S.length(),i,j; 24 int len = 0; 25 int minz = INF; 26 int flag = 0; 27 int ts = 0; 28 int a = 0; 29 for(i = 0 ; i < n; i++) 30 { 31 if(S[i]=='>') {flag = 1;a++;continue;} 32 if(S[i]=='<'&&!flag) {ts++;continue;} 33 int ss = ts,b = 0; 34 for(j = i ; j < n; j++) 35 if(S[j]=='>') ss++; 36 else b++; 37 ss+=abs(a-b); 38 ts++; 39 cout<<ss<<" "<<a<<" "<<b<<endl; 40 if(ss<minz) 41 { 42 len = min(a,b)*2; 43 minz = ss; 44 } 45 } 46 return len; 47 } 48 };