T1
Description
给定$N$个点,问这$N$个点能构成的三角形个数。
Input
第一行一个整数$N$,代表点数。
接下来$N$行,每行两个非负整数$X,Y$,表示一个点的坐标。
Output
一个非负整数,即构成三角形个数。
Sample Input
5
0 0
1 0
2 0
0 1
1 1
Sample Output
9
HINT
$N;leq;100$,保证任意两点不重合,坐标$;leq;10000$.
Solution
只要三点不共线就能组成三角形了。是否共线用斜率或叉积判即可。
#include<cmath> #include<ctime> #include<stack> #include<queue> #include<cstdio> #include<vector> #include<cstring> #include<cstdlib> #include<iostream> #include<algorithm> #define N 105 #define eps 1e-11 using namespace std; struct point{ int x,y; }a[N]; int n,ans;double d1,d2,d3; inline double sqr(int k){ return (double)(k*k); } inline point dec(point x,point y){ return (point){x.x-y.x,x.y-y.y}; } inline int mult(point x,point y){ return x.x*y.y-x.y*y.x; } inline double dis(point x,point y){ point z=dec(x,y); return sqrt(sqr(z.x)+sqr(z.y)); } inline bool cmp(double x,double y){ return x>y&&fabs(x-y)>eps; } inline void init(){ scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d%d",&a[i].x,&a[i].y); for(int i=1;i<n;i++) for(int j=i+1;j<n;j++) for(int k=j+1;k<=n;k++) if(mult(dec(a[i],a[j]),dec(a[j],a[k]))) ++ans; printf("%d ",ans); } int main(){ freopen("tri.in","r",stdin); freopen("tri.out","w",stdout); init(); fclose(stdin); fclose(stdout); return 0; }
T2
Description
为了测试小$M$的英语水平,$Mr.R$让小$M$写英语作文,小$M$则把作文交给了小$W$写。
然而$Mr.R$总结出了那个小$W$写作文的习惯,也就是某些关键的字符串。如果一篇作文中这若干个关键字符串都出现,他就认为这是小$W$写的。注意,小$W$可能写多篇作文。
Input
第一行一个整数$N$,表示关键字符串的个数,$N;leq;100$。
接下来$N$行,每行为一个长度不超过$100$的字符串。
最后是若干段文本,每段文本以$$$结尾。
由于写作文的人太疯狂,每篇作文最长可以达到$1350000$个字符,但作文的个数不超过$10$。
Output
对于每一段文本对应一行输出。
$’Yes’$表示是小W的作文,$’No’$表示不是。
请注意大小写。
Sample Input
3
i
love
m
ilovem
Sample Output
Yes
No
HINT
$N;leq;100$
Solution
这题用字符串哈希和$KMP$可以拿到$90$分,$AC$自动机能$A$(因为它是$AC$自动机的裸题)。
为何这题不简述题面?因为小W帮小M写的作文是“ilovem”(被耽美毒害的我)
#include<cmath> #include<ctime> #include<stack> #include<queue> #include<cstdio> #include<vector> #include<cstring> #include<cstdlib> #include<iostream> #include<algorithm> #define N 105 #define T 10005 #define M 1350005 using namespace std; struct trie{ int chl[26],nxt; }t[T]; int a[M],b[N],l,m,n,cnt; char c[M]; bool v[T];queue<int> q; inline int read(){ int ret=0;char c=getchar(); while(!isdigit(c)) c=getchar(); while(isdigit(c)){ ret=ret*10+c-'0'; c=getchar(); } return ret; } inline void insert(int a[],int l){ for(int i=1,u=0;i<=l;i++){ if(!t[u].chl[a[i]]) t[u].chl[a[i]]=++cnt; u=t[u].chl[a[i]]; } } inline void get_nxt(){ for(int i=0;i<26;i++) if(t[0].chl[i]) q.push(t[0].chl[i]); while(!q.empty()){ int u=q.front();q.pop(); for(int i=0,j,c;i<26;i++){ if(c=t[u].chl[i]){ q.push(c);j=t[u].nxt; while(j&&!t[j].chl[i]) j=t[j].nxt; t[c].nxt=t[j].chl[i]; } } } } inline bool chk(){ memset(v,0,sizeof(v)); for(int i=1,j=0;i<=m;i++){ while(j&&!t[j].chl[a[i]]) j=t[j].nxt; if(t[j].chl[a[i]]) j=t[j].chl[a[i]]; v[j]=true; for(int k=t[j].nxt;k&&!v[k];k=t[k].nxt) v[k]=true; } for(int i=1;i<=cnt;i++) if(!v[i]) return false; return true; } inline void init(){ scanf("%d",&n); while(n--){ scanf("%s",c+1); l=strlen(c+1); for(int i=1;i<=l;i++) b[i]=c[i]-'a'; insert(b,l); } get_nxt(); while(scanf("%s",c+1)!=EOF){ m=strlen(c+1)-1; for(int i=1;i<=m;i++) a[i]=c[i]-'a'; if(chk()) printf("Yes "); else printf("No "); } } int main(){ freopen("letter.in","r",stdin); freopen("letter.out","w",stdout); init(); fclose(stdin); fclose(stdout); return 0; }
T3
Description
在二维坐标系中有$N$面镜子(镜子坐标绝对值不超过$M$),镜子均与坐标轴成$45$°角,所以一共有两种类型“/”和“”。原点不会有镜子,任意一点最多只有一面镜子。
镜子两个面都能反光,而中间不透光,例如,对于一个“/”型镜子,下方向射入的光线会被反射到右方向,左方向射入的光线会被反射到上方向。
现在有一条光线从原点沿$x$轴正方向射出,求走过T路程后所在位置。
Input
第一行三个整数$N,M,T$。
第$2$到$N+1$行,每行两个整数$X_i,Y_i$,表示镜子坐标,一个字符$S_i$表示镜子类型。
Output
一行两个整数,表示走过T路程后的坐标。
Sample Input
5 2 8
0 1
0 2 /
1 0 /
1 1
1 2
Sample Output
3 1
HINT
$N;leq;10^5,M;leq;10^9,T;leq;10^{18}$
Solution
每面镜子对于一个方向反射出光线,会到达的镜子(如果有的话)是固定的。
所以可以预处理出每面镜子向$4$个方向反射出光线会到达的镜子是哪个($sort$后乱搞即可)。
然后直接模拟+判环就可以过了。
时间复杂度$O(nlogn+n)$。
#include<cmath> #include<ctime> #include<stack> #include<queue> #include<cstdio> #include<vector> #include<cstring> #include<cstdlib> #include<iostream> #include<algorithm> #define N 100005 using namespace std; typedef long long ll; struct point{ ll x,y;int n,ty; }a[N]; int nxt[5][N],dir[2][5],n,m,u; ll t,v[5][N]; inline int read(){ int ret=0,f=1; char c=getchar(); while(!isdigit(c)){ if(c=='-') f=-1; c=getchar(); } while(isdigit(c)){ ret=ret*10+c-'0'; c=getchar(); } return ret*f; } inline ll read_ll(){ ll ret=0,f=1; char c=getchar(); while(!isdigit(c)){ if(c=='-') f=-1; c=getchar(); } while(isdigit(c)){ ret=ret*10+c-'0'; c=getchar(); } return ret*f; } inline char read_c(){ char c=getchar(); while(c!='\'&&c!='/') c=getchar(); return c; } inline bool cmpx(point x,point y){ if(x.x!=y.x) return x.x<y.x; return x.y<y.y; } inline bool cmpy(point x,point y){ if(x.y!=y.y) return x.y<y.y; return x.x<y.x; } inline bool cmpi(point x,point y){ return x.n<y.n; } inline ll dis(point x,point y){ if(x.x==y.x) return abs(x.y-y.y); return abs(x.x-y.x); } inline void init(){ n=read();m=read();t=read_ll(); for(int i=1;i<=n;i++){ a[i].n=i; a[i].x=read_ll(); a[i].y=read_ll(); if(read_c()=='/') a[i].ty=1; } sort(a+1,a+1+n,cmpx); for(int i=1,j;i<=n;i=j){ for(j=i+1;j<=n&&a[j].x==a[i].x;j++); for(int k=i+1;k<j;k++) nxt[3][a[k].n]=a[k-1].n; for(int k=j-2;k>=i;k--) nxt[1][a[k].n]=a[k+1].n; } sort(a+1,a+1+n,cmpy); for(int i=1,j;i<=n;i=j){ if(!a[i].y) for(int k=i;k<=n&&!a[k].y;k++) if(a[k].x>0){ u=a[k].n;break; } for(j=i+1;j<=n&&a[j].y==a[i].y;j++); for(int k=i+1;k<j;k++) nxt[2][a[k].n]=a[k-1].n; for(int k=j-2;k>=i;k--) nxt[4][a[k].n]=a[k+1].n; } sort(a+1,a+1+n,cmpi); dir[0][1]=2;dir[0][2]=1; dir[0][3]=4;dir[0][4]=3; dir[1][1]=4;dir[1][2]=3; dir[1][3]=2;dir[1][4]=1; if(!u||t<=a[u].x){ printf("%lld 0 ",t); return; } t-=a[u].x;int cnt=0; for(int d=dir[a[u].ty][4],k;t;){ ++cnt;if(cnt>100005*8) return; k=nxt[d][u]; if(v[d][u]) t=t%(v[d][u]-t); if(!k||t<=dis(a[k],a[u])){ if(d==1) printf("%lld %lld ",a[u].x,a[u].y+t); else if(d==2) printf("%lld %lld ",a[u].x-t,a[u].y); else if(d==3) printf("%lld %lld ",a[u].x,a[u].y-t); else printf("%lld %lld ",a[u].x+t,a[u].y); return; } v[d][u]=t;t-=dis(a[k],a[u]); d=dir[a[k].ty][d];u=k; } } int main(){ freopen("mir.in","r",stdin); freopen("mir.out","w",stdout); init(); fclose(stdin); fclose(stdout); return 0; }