GYM 101667H Rock Paper Scissors(FFT)
Posted lalalatianlalu
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了GYM 101667H Rock Paper Scissors(FFT)相关的知识,希望对你有一定的参考价值。
题意:给你一个串a,是有R,S,P(石头剪刀布)构成的,然后还有一个序列b是你的出牌顺序,但你可以跳过机器的前x个出牌,从x+1开始出,问你最多赢几次
思路:好烦啊,这个题下午一直不会做,感觉和之前学弟将的一个模糊匹配的很像,但好像也不怎么像,挂机一下午。
这个题其实是利用了卷积的性质,我们先考虑单独的每一个字母,因为我们在卷积的时候不能牵扯其他的字符,如果有其他的字符,就类似于模糊匹配了,那是我们只是用FFT加速多项式乘法,而这道题的FFT其实是用FFT算出对于(FFT后的)第i个位置,我们字符匹配后所得到的价值,所以我们把三种字符都加起来,然后取max,其实不是很难理解
代码:(逆fft的时候忘记除n,找了很久,很久不写FFT,基本忘得差不多了)
#include <bits/stdc++.h> using namespace std; const int N = 400005; const double PI=acos(-1.0); struct cp { double r,i; cp(){} cp(double _r,double _i) { r=_r;i=_i; } cp operator +(const cp a)const { return cp(a.r+r,a.i+i); } cp operator -(const cp a)const { return cp(r-a.r,i-a.i); } cp operator *(const cp a)const { return cp(r*a.r-i*a.i,r*a.i+i*a.r); } cp conj() { return cp(r,-i); } }; int n=1,m; cp f[N],g[N],omg[N],inv[N]; void FFT_init(){ for(int i=0;i<n;i++){ omg[i]=cp(cos(2*PI*i/n),sin(2*PI*i/n)); inv[i]=omg[i].conj(); } } void fft(cp *a,cp *omg){ int lim=0; while((1 << lim) < n) lim++; for(int i=0;i<n;i++){ int t=0; for(int j=0;j<lim;j++) if(i >> j&1) t |= 1 << (lim - j - 1); if(i<t) swap(a[i],a[t]); } for(int l=2;l<=n;l*=2){ int m=l/2; for(cp *p=a;p!=a+n;p+=l){ for(int i=0;i<m;i++){ cp t=omg[n/l*i]*p[m+i]; p[m+i]=p[i]-t; p[i]=p[i]+t; } } } } int res[N],sum[N]; char a[N],b[N]; int lena,lenb; void solve(char c) { for(int i=0;i<lena;i++){ if(a[i]==c)f[i].r=1; else f[i].r=0; f[i].i=0; } for(int i=lena;i<n;i++){ f[i].r=0;f[i].i=0; } for(int i=0;i<lenb;i++){ if(b[i]==c)g[i].r=1; else g[i].r=0; g[i].i=0; } for(int i=lenb;i<n;i++){ g[i].r=0;g[i].i=0; } fft(f,omg),fft(g,omg); for(int i=0;i<n;i++)f[i]=f[i]*g[i]; fft(f,inv); for(int i=0;i<n;i++){ sum[i]=(int)(f[i].r/n+0.5); } for(int i=0;i<n;i++){ res[i]+=sum[i]; } } int main() { scanf("%d%d",&lena,&lenb); scanf("%s%s",a,b); for(int i=0;i<lena;i++){ if(a[i]==‘S‘)a[i]=‘R‘; else if(a[i]==‘R‘)a[i]=‘P‘; else if(a[i]==‘P‘)a[i]=‘S‘; } reverse(b,b+lenb); while(n<lena*2||n<lenb*2)n<<=1; FFT_init(); solve(‘S‘); solve(‘R‘); solve(‘P‘); int ans=0; for(int i=lenb-1;i<lena+lenb-1;i++){ ans=max(ans,res[i]); } printf("%d ",ans); return 0; } /* 12 4 RSPPSSSRRPPR RRRR */
以上是关于GYM 101667H Rock Paper Scissors(FFT)的主要内容,如果未能解决你的问题,请参考以下文章
Python 3 : Rock, Paper, Scissor game - 如何定义获胜次数和选择次数
Rock-Paper-Scissors Tournament[HDU1148]