• 2018宁夏网络赛H题 FFT


    https://nanti.jisuanke.com/t/A1676

    题意:给两个字符串代表出石头剪子布的顺序且第二个字符串长度小于等于第一个字符串,问第二个字符串从什么时候开始和第一个比较可以赢得最多。

    假设题目给出第一个字符串abcde,第二个字符串 fghi

    将第二个字符串逆转,然后将他们将他们转化为字符串就是

    f(x) = a + bx1 + cx2 + dx3 + ex4

    g(x) = i + hx1 + gx2 + fx3

    两式相乘,发现x4就是bcde 和fghi匹配的系数,x3就是abcd和fghi匹配的系数。

    因此,要将最终答案转化为这种情况的系数,我们就需要对每一种克制关系,例如a > b,a > c,的情况

    将g(x)中a的系数变为1,f(x)中bc的系数变为1,走一遍fft,可以得出每种情况下这对克制关系会产生多少赢的情况

    时间复杂度n * lnn * 5

    #include <map>
    #include <set>
    #include <ctime>
    #include <cmath>
    #include <queue>
    #include <stack>
    #include <vector>
    #include <string>
    #include <bitset>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <sstream>
    #include <iostream>
    #include <algorithm>
    #include <functional>
    using namespace std;
    #define For(i, x, y) for(int i=x;i<=y;i++)  
    #define _For(i, x, y) for(int i=x;i>=y;i--)
    #define Mem(f, x) memset(f,x,sizeof(f))  
    #define Sca(x) scanf("%d", &x)
    #define Sca2(x,y) scanf("%d%d",&x,&y)
    #define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z)
    #define Scl(x) scanf("%lld",&x)  
    #define Pri(x) printf("%d
    ", x)
    #define Prl(x) printf("%lld
    ",x)  
    #define CLR(u) for(int i=0;i<=N;i++)u[i].clear();
    #define LL long long
    #define ULL unsigned long long  
    #define mp make_pair
    #define PII pair<int,int>
    #define PIL pair<int,long long>
    #define PLL pair<long long,long long>
    #define pb push_back
    #define fi first
    #define se second 
    typedef vector<int> VI;
    int read(){int x = 0,f = 1;char c = getchar();while (c<'0' || c>'9'){if (c == '-') f = -1;c = getchar();}
    while (c >= '0'&&c <= '9'){x = x * 10 + c - '0';c = getchar();}return x*f;}
    const double eps = 1e-9;
    const int maxn = 1e6 + 10;
    const int INF = 0x3f3f3f3f;
    const int mod = 1e9 + 7; 
    const double PI = acos(-1.0);
    int N,M,K;
    char str[maxn],str2[maxn];
    int ans[maxn << 2],r[maxn << 2];
    pair<char,char> eat[10];
    const char c[10] = {0,'R','P','S','L','K'};
    struct complex{
        double x,y;
        complex(double x = 0,double y = 0):x(x),y(y){}
        void init(){x = y = 0;}
        friend complex operator + (complex a,complex b){return complex(a.x + b.x,a.y + b.y);}
        friend complex operator - (complex a,complex b){return complex(a.x - b.x,a.y - b.y);}
        friend complex operator * (complex a,complex b){return complex(a.x * b.x - a.y * b.y,a.x * b.y + a.y * b.x);}
    }a[maxn << 2],b[maxn << 2];
    void init(){
        eat[1] = mp('L','S');
        eat[2] = mp('R','K');
        eat[3] = mp('P','L');
        eat[4] = mp('K','P');
        eat[5] = mp('S','R');
    }
    void FFT(int limit,complex *A,int *r,int type){
        for(int i = 0 ; i < limit; i ++){
            if(i < r[i]) swap(A[i],A[r[i]]);
        }
        for(int mid = 1; mid < limit; mid <<= 1){
            int len = mid << 1;
            complex Wn(cos(PI / mid),type * sin(PI / mid));
            for(int j = 0; j < limit; j += len){
                complex w(1,0);
                for(int k = 0; k < mid; k ++,w = w * Wn){
                    complex x = A[j + k],y = w * A[j + mid + k];
                    A[j + k] = x + y;
                    A[j + mid + k] = x - y;
                }
            }
        }
    }
    int main(){
        scanf("%s%s",str,str2); init();
        N = strlen(str); M = strlen(str2);
        for(int i = 0; i < M; i ++){
            if(i >= M - i - 1) break;
            swap(str2[i],str2[M - i - 1]);
        }
        N--; M--;
        int limit = 1,l = 0; while(limit <= N + M) limit <<= 1,l++;
        for(int i = 0 ; i < limit; i ++) r[i] = (r[i >> 1] >> 1) | ((i & 1) << (l - 1));
        for(int k = 1; k <= 5; k ++){
            for(int i = 0 ; i < limit; i ++) a[i].init(),b[i].init();
            for(int i = 0 ; i <= N ; i ++) a[i].x =(str[i] == eat[k].fi || str[i] == eat[k].se);
            for(int i = 0 ; i <= M ; i ++) b[i].x =(str2[i] == c[k]);
            FFT(limit,a,r,1); FFT(limit,b,r,1);
            for(int i = 0 ; i < limit; i ++) a[i] = a[i] * b[i];
            FFT(limit,a,r,-1);
            for(int i = 0 ; i <= N + M; i ++) ans[i] += (int)(a[i].x / limit + 0.5); 
        } 
        int Max = 0;
        for(int i = 0 ; i < limit; i ++) Max = max(Max,ans[i]);
        Pri(Max);
        return 0;
    }
  • 相关阅读:
    Silverlight第三方控件收集
    我们三十以后才明白
    修复编译Silverlight&quot;不能找到AppManifest.xaml&rdquo;的错误
    Android消息通知
    理解和认识udev
    QT进度条
    WARNING: Application does not specify an API level requirement!
    Linux设备驱动中的异步通知与异步I/O
    Qtopia2.2.0 的配置和交叉编译
    Android Menus
  • 原文地址:https://www.cnblogs.com/Hugh-Locke/p/11195866.html
Copyright © 2020-2023  润新知