20160814 训练记录
1. tri
给出$n$个点,求有多少个三元点对能组成三角形。
$n \leq 100$
【题解】枚举即可。
如果$n \leq 1000$,减法原理,对于三点共线,枚举中间点,极角排序即可。复杂度$O(n^2logn)$
# include <stdio.h> using namespace std; int n; struct point { int x, y; }p[110]; int ans = 0; int main() { freopen("tri.in", "r", stdin); freopen("tri.out", "w", stdout); scanf("%d", &n); for (int i=1; i<=n; ++i) scanf("%d%d", &p[i].x, &p[i].y); for (int i=1; i<=n; ++i) for (int j=1; j<=n; ++j) for (int k=1; k<=n; ++k) { if(i==j || i==k || j==k) continue; if(p[i].x - p[j].x == 0 || p[j].x - p[k].x == 0) { if(p[i].x - p[j].x == 0 && p[j].x - p[k].x != 0) ++ans; else if(p[i].x - p[j].x != 0 && p[j].x - p[k].x == 0) ++ans; continue; } int dy1=p[i].y-p[j].y, dy2=p[j].y-p[k].y; int dx1=p[i].x-p[j].x, dx2=p[j].x-p[k].x; if((long double)dy1/dx1 != (long double)dy2/dx2) ++ans; } ans /= 6; printf("%d\n", ans); return 0; }
2. letter
给出n个长度小于100的模式串,给出m个长度小于1350000的字符串,问这个字符串中是否出现了所有的n个模式串。
$n \leq 100, m \leq 10$
【题解】kmp即可。当然正确做法是AC自动机。
# include <stdio.h> # include <string.h> # include <algorithm> using namespace std; int n; char str[110][110]; int len[110]; int next[110][110]; char p[1360001]; inline void getnext(int pos) { next[pos][1] = 0; len[pos] = strlen(str[pos]+1); int j = 0; for (int i=2; i<=len[pos]; ++i) { while(j>0 && str[pos][j+1] != str[pos][i]) j=next[pos][j]; if(str[pos][j+1] == str[pos][i]) ++j; next[pos][i] = j; } } inline bool kmp(int pos) { int j=0; int leng = strlen(p+1); // printf("%s", p+1); for (int i=1; i<=leng; ++i) { while(j>0 && str[pos][j+1] != p[i]) j=next[pos][j]; if(str[pos][j+1] == p[i]) ++j; if(j == len[pos]) return 1; } return 0; } int main() { freopen("letter.in", "r", stdin); freopen("letter.out", "w", stdout); scanf("%d", &n); for (int i=1; i<=n; ++i) scanf("%s", str[i]+1); random_shuffle(str+1, str+n+1); for (int i=1; i<=n; ++i) getnext(i); while(~scanf("%s", p+1)) { p[strlen(p+1)] = '\0'; // printf("checking %s\n", p); bool flag = 0; for (int i=1; i<=n; ++i) { // printf("===nowchecking %s\n", str[i]+1); bool gg = kmp(i); if(gg == 0) { flag = 1; break; } } if(flag) puts("No"); else puts("Yes"); } return 0; }
AC自动机有点问题……我去调一下
具体就是这个数据会有问题:
2
ay
gay
gay$
答案应该是Yes,但是有些会输出No
啊更新完成 (upd 20160818)
# include <stdio.h> # include <string.h> # include <queue> # include <algorithm> using namespace std; int n; int len[110], x; char ps[1360001]; char str[510]; int ch[2000010][27], fail[2000010], last[2000010], cnt[2000010], siz; bool val[2000010]; inline void ACinsert() { int len = strlen(str), p=0; for (int i=0; i<len; ++i) { int c = str[i] - 'a'; if(!ch[p][c]) ch[p][c] = ++siz; p = ch[p][c]; } val[p] = 1; } queue<int> q; inline void ACgetfail() { fail[0] = 0; for (int c=0; c<26; ++c) { int p = ch[0][c]; if(p) { fail[p] = last[p] = 0; q.push(p); } } while(!q.empty()) { int top=q.front(); q.pop(); for (int c=0; c<26; ++c) { int p = ch[top][c]; if(!p) continue; q.push(p); int v = fail[top]; while(v && !ch[v][c]) v = fail[v]; fail[p] = ch[v][c]; last[p] = val[fail[p]] ? fail[p] : last[fail[p]]; } } } inline void ACadd(int x) { for (; x; x=last[x]) cnt[x] = 1; } inline void ACfind() { int p=0, len = strlen(ps); memset(cnt, 0, sizeof(cnt)); for (int i=0; i<len-1; ++i) { int c = ps[i] - 'a'; while(p && !ch[p][c]) p = fail[p]; p = ch[p][c]; if(val[p]) ACadd(p); else if(last[p]) ACadd(last[p]); } } int main() { freopen("letter.in", "r", stdin); freopen("letter.out", "w", stdout); scanf("%d", &n); for (int i=1; i<=n; ++i) scanf("%s", str), ACinsert(); ACgetfail(); while(~scanf("%s", ps)) { ACfind(); bool gg=0; for (int i=1; i<=siz; ++i) if(val[i] != 0) if(cnt[i] == 0) { gg=1; break; } if(gg) puts("No"); else puts("Yes"); } return 0; }
3. mir
给出n个反射镜,问一束光从原点沿x轴正方向射出,T时刻后到哪里。假设光一时刻走一个单位。反射镜均成45度或135度角,且两面都可以反射。
$n \leq 100000, T \leq 10^{18}$
【题解】
最普通的想法:按时间暴力
我们可以优化点,就是预处理出来,每次走一大段,这样就有85分啦
那么我们发现如果有环就会爆炸啦!
那么我们判环即可,如果有就把T拿去对于环长度取余。
判断环的时候注意一个反射镜拆成4个点
# include <stdio.h> # include <algorithm> # include <iostream> using namespace std; int n; long long T; struct mirror { int x, y, id; bool f; }p[666666]; char str[5]; int s[666666][5]; bool vis[2666666]; long long sx[2666666]; // right:1, up:2, left:3, down:4 inline void turn(int &FACE, bool g) { if(g == 1) { if(FACE == 1) FACE=2; else if(FACE == 2) FACE=1; else if(FACE == 3) FACE=4; else if(FACE == 4) FACE=3; } else { if(FACE == 1) FACE=4; else if(FACE == 2) FACE=3; else if(FACE == 3) FACE=2; else if(FACE == 4) FACE=1; } } inline int get(int id, int fx) { bool gg = p[id].f; /* if(gg == 1) {//"/" if(fx == 1 || fx == 2) return id; else return id+n; } else { if(fx == 1 || fx == 4) return id; else return id+n; }*/ if(fx == 1) return id; if(fx == 2) return id+n; if(fx == 3) return id+n+n; if(fx == 4) return id+n+n+n; } inline void go(long long &x, long long &y, long long T, int face) { if(face == 1) x=x+T; if(face == 2) y=y+T; if(face == 3) x=x-T; if(face == 4) y=y-T; } inline int cmp1(mirror a, mirror b) { return a.x < b.x || (a.x == b.x && a.y < b.y); } inline int cmp2(mirror a, mirror b) { return a.y < b.y || (a.y == b.y && a.x < b.x); } inline int cmp3(mirror a, mirror b) { return a.id < b.id; } int main() { freopen("mir.in", "r", stdin); freopen("mir.out", "w", stdout); scanf("%d%*d", &n); cin >> T; for (int i=1; i<=n; ++i) { scanf("%d%d%s", &p[i].x, &p[i].y, str); if(str[0] == '/') p[i].f=1; else p[i].f=0; p[i].id=i; s[i][1] = s[i][2] = s[i][3] = s[i][4] = -1; } sort(p+1, p+n+1, cmp1); for (int i=1; i<=n; ++i) { int begin = i, end = i; // printf("BEGIN=%d x=%d\n", begin, p[begin].x); while(p[begin].x == p[end+1].x) ++end; for (int j=begin; j<end; ++j) s[p[j].id][2] = p[j+1].id; for (int j=begin+1; j<=end; ++j) s[p[j].id][4] = p[j-1].id; // printf("END=%d x=%d\n", end, p[begin].x); i = end; } sort(p+1, p+n+1, cmp2); for (int i=1; i<=n; ++i) { int begin = i, end = i; while(p[begin].y == p[end+1].y) ++end; for (int j=begin; j<end; ++j) s[p[j].id][1] = p[j+1].id; for (int j=begin+1; j<=end; ++j) s[p[j].id][3] = p[j-1].id; i = end; } long long x=0, y=0; int face = 1; int id=-1, tem; for (int i=1; i<=n; ++i) { if(p[i].y == 0 && p[i].x > 0) { id=i; break; } } tem = p[id].id; if(id == -1 || T <= p[id].x) { cout << T << " 0\n"; return 0; } T = T-p[id].x; x = p[id].x; //cout << "face bef = " << face << ' ' << p[id].f << endl; turn(face, p[id].f); //cout << "face aft = " << face << endl; id = tem; //cout << x << ' ' << y << ' ' << T << ' ' << face << endl; sort(p+1, p+n+1, cmp3); /* for (int i=1; i<=n; ++i) { printf("right=%d, up=%d, left=%d, down=%d\n", s[i][1], s[i][2], s[i][3], s[i][4]); } */ bool incircle=0; long long TT = T; while(T>0) { if(id>n) id=id%n; // cout << x << ' ' << y << ' ' << T << ' ' << face << ' ' << id << endl; int next = s[id][face]; // printf("%d\n", next); if(next == -1) { go(x, y, T, face); T=0; continue; } long long dis; if(face == 1) dis = p[next].x - p[id].x; if(face == 2) dis = p[next].y - p[id].y; if(face == 3) dis = p[id].x - p[next].x; if(face == 4) dis = p[id].y - p[next].y; if(T <= dis) { go(x, y, T, face); T=0; continue; } go(x, y, dis, face); // cout << x << ' ' << y << endl; T-=dis; int ID=get(next, face); // printf("%d\n", ID); turn(face, p[ID>n?(ID%n):ID].f); if(vis[ID] && !incircle) { long long TIME = TT-T-sx[ID]; // printf("TIME=%d\n", TIME); T=T%TIME; incircle=1; } vis[ID] = 1; sx[ID] = TT - T; // printf("sx = %d\n", sx[ID]); id=ID; } cout << x << ' ' << y << endl; return 0; }
2023年6月17日 13:51
TeachersBadi is a website dedicated to education, students, and teachers.The name 'TeachersBadi' reveals the nature of the site. A dedicated Team for teachers, students, and educators is launching and running the site. teachersbadi.in We enjoy sharing primarily educational material and employee and teacher-related content in the educational area.