题目链接: www.acmore.net
Problem A
遍历数组a, 对于每一个元素 a[i], 统计区间 ( a[i], a[i]+d ] 有X个点,则符合条件的为 C(2,X)
累加就可以了
解题代码
#include<stdio.h> #include<string.h> #include<iostream> #include<algorithm> #include<vector> #include<map> using namespace std; typedef long long LL; const int N = 1e5+10; const int M = 1e6; map< LL, int > Mp; int n, C[M+10], size; LL a[N], d, b[M]; void update( int x ) { for(; x <= M; x += (x&(-x)) ) C[x] += 1; } int read( int x ) { int res = 0; for( ; x >= 1; x -= (x&(-x)) ) res += C[x]; return res; } int main() { while( scanf("%d%lld", &n, &d) != EOF) { Mp.clear(); size = 0; for(int i = 0; i < n; i++ ) { scanf("%lld", &a[i]); b[size++] = a[i]; b[size++] = a[i]+d; } sort( b, b+size ); size = unique( b, b+size) - b; int tmp = 1; for(int i = 0; i < size; i++) Mp[ b[i] ] = tmp++; memset( C, 0, sizeof(C)); for(int i = 0; i < n; i++) update( Mp[ a[i] ] ); LL ans = 0; for(int i = 0; i < n; i++) { int k = read( Mp[ a[i]+d ] ) - (i+1); if( k > 1 ) ans += 1LL*k*(k-1)/2; } printf("%lld\n", ans ); } return 0; }
Problem B
字符串处理,取最长的,当有多个,则字典序最大的是结果
解题代码
#include<stdio.h> #include<string.h> #include<stdlib.h> #include<vector> #include<iostream> #include<algorithm> using namespace std; char str[110][110]; vector< string > S; int main() { int n; while( scanf("%d", &n) != EOF ) { int L = 0; for(int i = 0; i < n; i++) { scanf("%s", str[i] ); if( strlen( str[i] ) > L ) L = strlen(str[i]); } S.clear(); for(int i = 0; i < n; i++) if( strlen(str[i]) == L ) S.push_back( str[i] ); sort( S.begin(), S.end() ); printf("%s\n", (S[ S.size()-1 ]).c_str() ); } return 0; }
Problem C
递推, F(N) = F(N-1)+ F(N-2)
解题代码
#include<stdio.h> typedef long long LL; LL f[55] = {1,1,2}; int main() { for(int i = 3; i <= 50; i++) f[i] = f[i-1]+f[i-2]; int a, b, T; scanf("%d", &T); while( T-- && scanf("%d%d", &a,&b) ) printf("%lld\n", f[b-a] ); return 0; }
Problem D
枚举长度O(N),之后枚举左边界O(N), 使用差值取模O( LogN ) 判定, 总时间复杂度为 O( N*N*LogN)
解题代码
#include<stdio.h> #include<stdlib.h> #include<string.h> typedef unsigned long long LL; char s1[1010]; int n; LL A[1010],B[1010], C[2][2020], T[1010]; void add(int key, int x, LL val ) { for(; x <= 1000; x+=(x&(-x))) C[key][x] += val; } LL read(int key, int x) { LL res = 0; for(; x >= 1; x -= (x&(-x)) ) res += C[key][x]; return res; } void init() { A[0] = B[0] = 0; for(int i = 1; i <= n; i++) { A[i] = (s1[i]-'a'+1)*T[i-1]; B[i] = (s1[n+1-i]-'a'+1)*T[i-1]; } memset( C, 0, sizeof(C)); for(int i = 1; i <= n; i++) { add( 0, i, A[i] ); add( 1, i, B[i] ); } } int find( int len ) { for(int i = 1; i+len-1 <= n; i++ ) { int a = i, b = i+len-1; int c = (n+1)-b, d = (n+1)-a; LL sa = read(0,b)-read(0,a-1); LL sb = read(1,d)-read(1,c-1); sa *= T[c-1]; sb *= T[a-1]; if( sa == sb ) return i; } return -1; } int main() { T[0] = 1; for(int i = 1; i <= 1010; i++) T[i] = T[i-1]*27; while( scanf("%s", s1+1) != EOF) { n = strlen(s1+1); init(); for(int m = n; m >= 1; m-- ) { int s = find(m); if( s != -1 ) { for(int i = s; i < s+m; i++) printf("%c", s1[i]); puts(""); break; } } } return 0; }
Problem E
按分数排序
解题代码
#include<stdio.h> #include<string.h> #include<algorithm> #include<iostream> #include<stdlib.h> using namespace std; const int N = 5150; struct node { char name[30]; double score; bool operator < ( node tmp ) const { return score > tmp.score; } void read( ) { scanf("%s %lf", name, &score ); } }stu[N]; int n, r; char str[30]; int main() { while( scanf("%d", &n) !=EOF) { for(int i = 0; i < n; i++) stu[i].read(); sort( stu, stu+n ); scanf("%d", &r); while( r-- ) { scanf("%s", str ); for(int i = 0; i < n; i++) if( strcmp( stu[i].name, str ) == 0 ) { printf("%d\n", i+1); break; } } } return 0; }
Problem F
BFS广搜即可,因为每个点至多走一次,也才10*10. 注意起点也算1步
解题代码
#include<stdio.h> #include<string.h> #include<stdlib.h> #include<iostream> #include<queue> using namespace std; char map[15][15]; int n, m, s; int vis[15][15]; struct node { int x, y; int step; }info,nxt; bool legal(int x, int y) { if( x >= 1 && x <= n && y >= 1 && y <= m ) return true; return false; } void getdir( int x1, int y1, int &x, int &y ) { switch( map[x1][y1] ) { case 'W': x = x1; y = y1-1; break; case 'E': x = x1; y = y1+1; break; case 'N': x = x1-1; y = y1; break; case 'S': x = x1+1; y = y1; break; } } queue<node> Q; void solve() { memset( vis , 0, sizeof(vis) ); while( !Q.empty() ) Q.pop(); info.x = 1; info.y = s; info.step = 1; Q.push(info); vis[info.x][info.y] = 1; while( !Q.empty() ) { info = Q.front(); Q.pop(); int x, y; getdir( info.x,info.y,x,y); if( !legal(x,y) ) { printf("%d step(s) to exit\n",info.step); return; } else if( vis[x][y] ) { printf("%d step(s) before a loop of %d step(s)\n", vis[x][y]-1, info.step-vis[x][y]+1); return; } else { vis[x][y] = info.step+1; nxt.step = info.step+1; nxt.x = x; nxt.y = y; Q.push(nxt); } } } int main() { while( scanf("%d%d%d", &n, &m, &s) != EOF) { if( !(n+m+s) ) break; for(int i = 1; i <= n; i++) scanf("%s", map[i]+1); solve(); } return 0; }
Problem G
位运算,异或, 当都为1时才为1,否则为0
初始令X = 0, 与所有数异或,那么相同的数,偶数个后都会为0,剩下的就是奇数个的值
注意,后台数据貌似没有 N=0,所以结束条件为 EOF,否则会TLE
解题代码
#include<stdio.h> int main() { int n; while( scanf("%d", &n) != EOF ) { if( n == 0 ) break; int a, x = 0; for(int i = 1; i <= n; i++) { scanf("%d", &a); x ^= a; } printf("%d\n", x); } return 0; }
Problem H
11年网络赛立体空间的简单版.
枚举两个水果成直线,然后扫其他水果. 利用叉积判定是否在直线上.
注意 坐标为 double类型. WA在了这上面
解题代码
#include<stdio.h> #define max(x,y) (x)>(y)?(x):(y) #define min(x,y) (x)<(y)?(x):(y) const int inf=0x7fffffff; typedef long long LL; struct node // Fruit { double x,y; void read( ) { scanf("%lf%lf", &x,&y); } }Q[1010]; const double esp = 1e-8; int sign(double x ) { return (x<-esp)? -1 : (x>esp); } bool judge( double x1,double y1,double x2,double y2,double x,double y ) { if( ( sign( ( x1-x )*( y2-y ) - ( x2-x )*( y1-y ) )) == 0 ) return true; return false; } int n; int main() { int T; scanf("%d", &T); for(int Case = 1; Case <= T; Case++ ) { scanf("%d", &n); int ans = 1; for(int i = 0; i < n; i++) Q[i].read(); for(int i = 0; i < n; i++) for(int j = i+1; j < n; j++) { int cnt = 2; for(int k = j+1; k < n; k++) { if( judge( Q[i].x, Q[i].y, Q[j].x, Q[j].y, Q[k].x, Q[k].y ) ) cnt++; } ans = max( ans, cnt ); } printf("Case %d: %d\n",Case, ans ); } return 0; }
Problem I
按要求使用栈模拟即可.
解题代码
#include<stdio.h> #include<stdlib.h> #include<string.h> #include<algorithm> #include<queue> #include<stack> #include<iostream> using namespace std; stack<string> s1, s2; string op, web, cur; int main() { int Case = 1; while( cin>>op ) { while( !s1.empty() ) s1.pop(); while( !s2.empty() ) s2.pop(); printf("Case %d:\n", Case++); cur = "http://www.acmore.net/"; cout << cur << endl; while( cin>>op ) { // cout << "op = " << op << endl; if( op == "end" ) { cout << "end" << endl; break; } else if( op == "visit" ) { cin >> web; // cout << "web = " << web << endl; while( !s2.empty() ) s2.pop(); s1.push( cur ); cur = web; cout << cur << endl; } else if( op == "back" ) { if( !s1.empty() ) { s2.push( cur ); cur = s1.top(); s1.pop(); cout << cur << endl; } else cout << "This is the first page" << endl; } else if( op == "forward" ) { if( !s2.empty() ) { s1.push( cur ); cur = s2.top(); s2.pop(); cout << cur << endl; } else cout << "This is the last page" << endl; } } } return 0; }
Problem J
模拟题.....
解题代码
#include <cstdio> #include <cstring> #include <cstdlib> #include <iostream> using namespace std; int num[10]; char G[1000][1000]; int main() { int N, M; while (scanf("%d %d", &N, &M), N|M) { memset(num, 0, sizeof (num)); for (int i = 0; i <= N*5; ++i) { scanf("%s", G[i]); } for (int i = 0; i < N; ++i) { for (int j = 0; j < M; ++j) { int cnt = 0; int l = i*5+1, r = i*5+4, u = j*5+1, d = j*5+4; for (int p = l; p <= r; ++p) { for (int q = u; q <= d; ++q) { if (G[p][q] == '*') { ++cnt; } } } num[cnt/4]++; } } for (int i = 0; i < 5; ++i) { printf(i == 0 ? "%d" : " %d", num[i]); } puts(""); } return 0; }