2017 多校联合训练 6 题解
Problem 1001
对于每个询问,根据后缀{前缀插入到AC自动机内
然后每个单词写2遍,中间用{隔开,统计有那几个前缀和后缀
最后对于每个前缀和后缀 输出方案数
注意:单词可能有重复,可以用vector记录一下end数组
1 #include<iostream> 2 #include<algorithm> 3 #include<cmath> 4 #include<cstring> 5 #include<queue> 6 #include<string> 7 #define next nxt 8 #define end ed 9 using namespace std; 10 int next[1200001][27],fail[1200001],dep[1200001]; 11 vector<int> end[1200001]; 12 int root,len; 13 int newnode(){ 14 for(int i=0;i<27;i++) 15 next[len][i]=-1; 16 end[len].clear(); 17 len++; 18 return len-1; 19 } 20 void clear(){ 21 len=0; 22 root=newnode(); 23 return; 24 } 25 void insert(char s[],int num){ 26 int ls=strlen(s); 27 int now=root; 28 for(int i=0;i<ls;i++){ 29 if(next[now][s[i]-'a']==-1) 30 next[now][s[i]-'a']=newnode(); 31 now=next[now][s[i]-'a']; 32 dep[now]=i+1; 33 } 34 end[now].push_back(num); 35 } 36 void build(){ 37 queue<int>q; 38 int i; 39 fail[root]=root; 40 for(i=0;i<27;i++){ 41 if(next[root][i]==-1) 42 next[root][i]=root; 43 else{ 44 fail[next[root][i]]=root; 45 q.push(next[root][i]); 46 } 47 } 48 while(!q.empty()){ 49 int now=q.front(); 50 q.pop(); 51 for(i=0;i<27;i++){ 52 if(next[now][i]==-1) 53 next[now][i]=next[fail[now]][i]; 54 else{ 55 fail[next[now][i]]=next[fail[now]][i]; 56 q.push(next[now][i]); 57 } 58 } 59 } 60 return; 61 } 62 int vis[1000010]; 63 void ask(char c[],int n,int num){ 64 bool flag1=false; 65 int lc=num; 66 int now=root; 67 int i; 68 for(i=0;i<lc;i++){ 69 now=next[now][c[i]-'a']; 70 int temp=now; 71 while(temp!=root){ 72 if(end[temp].size()&&dep[temp]<=n){ 73 flag1=1; 74 for (auto u:end[temp]) 75 vis[u]++; 76 } 77 temp=fail[temp]; 78 } 79 } 80 } 81 char s[2000001],t[2000001],ss[2000001],tt[2000001]; 82 char *si[100010]; 83 int n,m,le[100010],le2[100010]; 84 int main(){ 85 int i,j; 86 int _; 87 scanf("%d",&_); 88 while(_--){ 89 scanf("%d%d",&n,&m); 90 clear(); 91 for (i=1,j=0;i<=n;i++) 92 { 93 si[i]=ss+j; 94 scanf("%s",si[i]); 95 le[i]=strlen(si[i])+1; 96 j+=le[i]; 97 strcpy(ss+j,si[i]); 98 ss[j-1]='z'+1; 99 j+=le[i]; 100 101 le2[i]=strlen(si[i]); 102 } 103 for(i=1;i<=m;i++) 104 { 105 s[0]='z'+1; 106 scanf("%s%s",s+1,t); 107 strcat(t,s); 108 insert(t,i); 109 } 110 build(); 111 memset(vis,0,sizeof(vis)); 112 int ans=0; 113 //for(i=1;i<=m;i++){ 114 for (i=1;i<=n;i++) 115 { 116 //strcpy(tt,si[i].c_str()); 117 ask(si[i],le[i],le2[i]); 118 } 119 //} 120 for (i=1;i<=m;i++) 121 printf("%d ",vis[i]); 122 } 123 return 0; 124 }
Problem 1002
这里不总是在中垂线上的点取到最小值
通过观察可发现,当两个点离半径的距离到一定的程度时答案保持不变
算出这个距离即可
另外要注意这两个点可能会重合
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstdlib> 5 #include<algorithm> 6 #include<cstring> 7 #include<string> 8 #include<vector> 9 #include<map> 10 #include<set> 11 #include<queue> 12 using namespace std; 13 const double eps=1e-7; 14 #define y1 jkhjk 15 #define y2 erjkf 16 #define y3 jkdfhdw 17 #define y4 jkhjkff 18 #define y5 kjhkk 19 int _; 20 double r,x1,y1,x2,y2; 21 int main() 22 { 23 scanf("%d",&_); 24 while (_--) 25 { 26 scanf("%lf",&r); 27 scanf("%lf%lf",&x1,&y1); 28 scanf("%lf%lf",&x2,&y2); 29 if (x1==0&&y1==0) 30 { 31 printf("%.9f ",r*2); 32 continue; 33 } 34 if (fabs(x1-x2)<=eps&&fabs(y1-y2)<=eps) 35 { 36 double rest=r-sqrt(x1*x1+y1*y1); 37 printf("%.9f ",rest*2); 38 continue; 39 } 40 double x3=(x1+x2)/2; 41 double y3=(y1+y2)/2; 42 if (fabs(y1-y2)<=eps) 43 { 44 double x4=x3; 45 double y4=sqrt(r*r-x3*x3); 46 double x5=x3; 47 double y5=-sqrt(r*r-x3*x3); 48 double x6,y6,x7,y7; 49 double bili=sqrt(x1*x1+y1*y1)/r; 50 x6=x1/bili; 51 y6=y1/bili; 52 x7=x2/bili; 53 y7=y2/bili; 54 double dist=sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1)); 55 double pp=sqrt(x1*x1+y1*y1); 56 double ans=9999999; 57 double sita=(dist/(2*pp)); 58 //cout<<sita<<endl; 59 sita=sqrt(1.0-sita*sita); 60 if (sqrt(x1*x1+y1*y1)>=r*sita-eps) 61 ans=sqrt((x7-x6)*(x7-x6)+(y7-y6)*(y7-y6)); 62 ans=min(ans,sqrt((x4-x1)*(x4-x1)+(y4-y1)*(y4-y1))*2); 63 ans=min(ans,sqrt((x5-x1)*(x5-x1)+(y5-y1)*(y5-y1))*2); 64 printf("%.9f ",ans); 65 66 } 67 else 68 { 69 double k; 70 if (x1==x2) k=0; 71 else 72 k=(x2-x1)/(y1-y2); 73 double a=1+k*k; 74 double b=2*k*y3-2*k*k*x3; 75 double c=k*k*x3*x3-2*k*x3*y3+y3*y3-r*r; 76 double det=b*b-4*a*c; 77 double x4=(-b+sqrt(det))/(2*a); 78 double y4=k*(x4-x3)+y3; 79 double x5=(-b-sqrt(det))/(2*a); 80 double y5=k*(x5-x3)+y3; 81 double x6,y6,x7,y7; 82 double bili=sqrt(x1*x1+y1*y1)/r; 83 x6=x1/bili; 84 y6=y1/bili; 85 x7=x2/bili; 86 y7=y2/bili; 87 double dist=sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1)); 88 double pp=sqrt(x1*x1+y1*y1); 89 double ans=9999999; 90 double sita=(dist/(2*pp)); 91 sita=sqrt(1.0-sita*sita); 92 if (sqrt(x1*x1+y1*y1)>=r*sita-eps) 93 ans=sqrt((x7-x6)*(x7-x6)+(y7-y6)*(y7-y6)); 94 ans=min(ans,sqrt((x4-x1)*(x4-x1)+(y4-y1)*(y4-y1))*2); 95 ans=min(ans,sqrt((x5-x1)*(x5-x1)+(y5-y1)*(y5-y1))*2); 96 printf("%.9f ",ans); 97 } 98 } 99 return 0; 100 }