【ContestHunter】【弱省胡策】【Round2】
官方题解:http://wyfcyx.is-programmer.com/posts/95490.html
A
目前只会30分的暴力……DP好像很神的样子0.0(听说可以多次随机强行算?
1 //Round2 A 2 #include<cstdio> 3 #include<cstring> 4 #include<cstdlib> 5 #include<iostream> 6 #include<algorithm> 7 #define rep(i,n) for(int i=0;i<n;++i) 8 #define F(i,j,n) for(int i=j;i<=n;++i) 9 #define D(i,j,n) for(int i=j;i>=n;--i) 10 #define pb push_back 11 using namespace std; 12 typedef long long LL; 13 inline int getint(){ 14 int r=1,v=0; char ch=getchar(); 15 for(;!isdigit(ch);ch=getchar()) if (ch=='-') r=-1; 16 for(; isdigit(ch);ch=getchar()) v=v*10-'0'+ch; 17 return r*v; 18 } 19 const int N=110; 20 /*******************template********************/ 21 int n,m; 22 double a[10][110]; 23 24 void work1(){ 25 double ans=1.0; 26 F(i,1,m) ans*=(1.0-a[1][i]); 27 printf("%.9f\n",1.0-ans); 28 } 29 void work2(){ 30 double ans=0.0; 31 F(i,1,m) ans*=(1.0-a[1][i]); 32 } 33 int mp[10][110],my[N]; 34 bool vis[N]; 35 long double ans=0.0,gailv=1.0; 36 37 bool go(int x){ 38 F(i,1,m) 39 if (mp[x][i] && !vis[i]){ 40 vis[i]=1; 41 if (!my[i]||go(my[i])){ 42 my[i]=x; 43 return 1; 44 } 45 } 46 return 0; 47 } 48 void check(){ 49 // F(i,1,n){ F(j,1,m) printf("%d ",mp[i][j]); puts("");} 50 int tmp=0; 51 memset(my,0,sizeof my); 52 F(i,1,n){ 53 memset(vis,0,sizeof vis); 54 if (go(i)) tmp++; 55 } 56 double gl=gailv; 57 // printf("%d %.9f\n\n",tmp,gl); 58 ans+=tmp*gailv; 59 } 60 void dfs(int x,int y){ 61 // printf("dfs %d %d\n",x,y); 62 if (x==n+1){check();return;} 63 D(i,1,0){ 64 mp[x][y]=i; 65 gailv*=i*a[x][y]+(1-i)*(1.0-a[x][y]); 66 if (y==m) dfs(x+1,1); 67 else dfs(x,y+1); 68 mp[x][y]=0; 69 gailv/=i*a[x][y]+(1-i)*(1.0-a[x][y]); 70 } 71 } 72 void work3(){ 73 dfs(1,1); 74 double as=ans; 75 printf("%.9f\n",as); 76 } 77 int main(){ 78 #ifndef ONLINE_JUDGE 79 freopen("A.in","r",stdin); 80 freopen("A.out","w",stdout); 81 #endif 82 n=getint(); m=getint(); 83 F(i,1,n) F(j,1,m) scanf("%lf",&a[i][j]); 84 if (n==1) work1(); 85 // else if (n==2) work2(); 86 else 87 work3(); 88 return 0; 89 }
C
原来是用FFT来做的好题!
第一步用KMP比较简单,容易想到。
这题的特点是每个字符都是0或1,所以考虑第二步的时候,可以用FFT来进行快速运算0.0太神了!利用卷积的特点,将一个串反转过来,然后相同的,会对答案贡献1,不同的贡献0,卷积一下就是两个串对应位置都是1的位数!太神奇了。。。(都是0的位数求法:整个异或一下,0变1,1变0)
1 //Round2 C 2 #include<cmath> 3 #include<cstdio> 4 #include<cstring> 5 #include<cstdlib> 6 #include<iostream> 7 #include<algorithm> 8 #define rep(i,n) for(int i=0;i<n;++i) 9 #define F(i,j,n) for(int i=j;i<=n;++i) 10 #define D(i,j,n) for(int i=j;i>=n;--i) 11 #define pb push_back 12 using namespace std; 13 typedef long long LL; 14 inline int getint(){ 15 int r=1,v=0; char ch=getchar(); 16 for(;!isdigit(ch);ch=getchar()) if (ch=='-') r=-1; 17 for(; isdigit(ch);ch=getchar()) v=v*10-'0'+ch; 18 return r*v; 19 } 20 const int N=1000010; 21 /*******************template********************/ 22 const double pi=acos(-1); 23 struct comp{ 24 double r,i; 25 comp(double r=0.0,double i=0.0):r(r),i(i){} 26 comp operator * (const comp &b)const{return comp(r*b.r-i*b.i,r*b.i+i*b.r);} 27 comp operator + (const comp &b)const{return comp(r+b.r,i+b.i);} 28 comp operator - (const comp &b)const{return comp(r-b.r,i-b.i);} 29 }A[N],B[N]; 30 31 int n,m,nxt[N],v[N],cnt,c[N],nn; 32 char a[N][10],b[N][10],a2[N],b2[N]; 33 void FFT(comp *a,int n,int type){ 34 for(int i=0,j=0;i<n;++i){ 35 if (i<j) swap(a[i],a[j]); 36 for(int k=n>>1;(j^=k)<k;k>>=1); 37 } 38 for(int m=1;m<n;m<<=1){ 39 double u=pi/m*type; comp wm(cos(u),sin(u)); 40 for(int i=0;i<n;i+=(m<<1)){ 41 comp w(1,0); 42 rep(j,m){ 43 comp &A=a[i+j+m],&B=a[i+j],t=w*A; 44 A=B-t; B=B+t; w=w*wm; 45 } 46 } 47 } 48 if (type==-1) rep(i,n) a[i].r/=n; 49 } 50 void KMP(){ 51 nxt[1]=nxt[2]=1; 52 int j=1; 53 F(i,2,m){ 54 while(j!=1 && strcmp(b[i],b[j])!=0) j=nxt[j]; 55 nxt[i+1]=strcmp(b[i],b[j])==0 ? ++j : 1; 56 } 57 j=1; 58 F(i,1,n){ 59 while(j!=1 && strcmp(a[i],b[j])!=0) j=nxt[j]; 60 if (strcmp(a[i],b[j])==0) j++; 61 if (j==m+1) v[++cnt]=i-m+1; 62 } 63 } 64 void work(int x){ 65 rep(i,nn) A[i]=B[i]=comp(0,0); 66 rep(i,n) if (a2[i+1]-'0'==x) A[i].r=1; 67 rep(i,m) if (b2[i+1]-'0'==x) B[m-(i+1)].r=1; 68 FFT(A,nn,1); FFT(B,nn,1); 69 rep(i,nn) A[i]=A[i]*B[i]; 70 FFT(A,nn,-1); 71 rep(i,n) c[i+1]+=(int)(A[i+m-1].r+0.5); 72 } 73 74 int main(){ 75 #ifndef ONLINE_JUDGE 76 freopen("C.in","r",stdin); 77 freopen("C.out","w",stdout); 78 #endif 79 n=getint(); m=getint(); 80 for(nn=1;nn<n+m-1;nn<<=1); 81 F(i,1,n){ 82 scanf("%s",a[i]); 83 a2[i]=a[i][7]; 84 a[i][7]='0'; 85 } 86 F(i,1,m){ 87 scanf("%s",b[i]); 88 b2[i]=b[i][7]; 89 b[i][7]='0'; 90 } 91 KMP(); 92 if (cnt) puts("Yes"); 93 else {puts("No");return 0;} 94 work(0); 95 work(1); 96 int ans1=1e9,ans2=0; 97 F(i,1,cnt) if (m-c[v[i]]<ans1){ 98 ans1=m-c[v[i]]; ans2=v[i]; 99 } 100 printf("%d %d\n",ans1,ans2); 101 return 0; 102 }