• LOJ6436 [PKUSC2018] 神仙的游戏 【FFT】


    题目分析:

    题目要求前后缀相同,把串反过来之后是一个很明显的卷积的形式。这样我们可以完成初步判断(即可以知道哪些必然不行)。

    然后考虑一下虽然卷积结果成立,但是存在问号冲突的情况。

    箭头之间应当不存在1。不然就和图上所画的一样。注意到它每隔len个跳一次,所以相当于调和级数,利用原有信息判断即可。

    字符串转化的方式有很多种。

    代码:

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 
     4 const int maxn = (1<<19)+5;
     5 
     6 const int mod = 998244353;
     7 const int gg = 3;
     8 
     9 char str[maxn];
    10 
    11 int n,m,len,a[maxn<<1],b[maxn<<1],ord[maxn<<1];
    12 
    13 int f[maxn<<1],iv;
    14 
    15 int fast_pow(int now,int pw){
    16     int ans = 1,dd = now,bit = 1;
    17     while(bit <= pw){
    18     if(bit & pw) {ans = (1ll*ans*dd)%mod;}
    19     dd = (1ll*dd*dd)%mod;
    20     bit<<=1;
    21     }
    22     return ans;
    23 }
    24 
    25 void fft(int *d,int dr){
    26     for(register int i=0;i<m;i++) if(i < ord[i]) swap(d[i],d[ord[i]]);
    27     for(register int i=1;i<m;i<<=1){
    28     int wn = fast_pow(gg,(mod-1)/(2*i));
    29     if(dr == -1) wn = fast_pow(wn,mod-2);
    30     for(register int j=0;j<m;j+=(i<<1)){
    31         for(register int k=0,w=1;k<i;k++,w = (1ll*w*wn)%mod){
    32         int x = d[j+k],y = (1ll*w*d[j+k+i])%mod;
    33         d[j+k] = x+y; d[j+k] >=mod?d[j+k]-=mod:1;
    34         d[j+k+i] = x-y;
    35         d[j+k+i] < 0?d[j+k+i]+=mod:1;
    36         }
    37     }
    38     }
    39     if(dr == -1){
    40     for(register int i=0;i<m;i++) d[i] = (1ll*d[i]*iv)%mod;
    41     }
    42 }
    43 
    44 void work(){
    45     int n = strlen(str);m = 1;
    46     while(m < 2*n){m<<=1;len++;} iv = fast_pow(m,mod-2);
    47     for(register int i=0;i<m;i++) ord[i] = (ord[i>>1]>>1)+((i&1)<<len-1);
    48 
    49     for(register int i=0;i<n;i++) {
    50     if(str[i] == '0') a[i] = 1;
    51     else if(str[i] == '1') b[n-i-1] = 1;
    52     }
    53     
    54     fft(a,1); fft(b,1); 
    55     for(register int i=0;i<m;i++) {
    56     f[i] = (1ll*a[i]*b[i])%mod;
    57     }
    58     
    59     memset(a,0,sizeof(a)); memset(b,0,sizeof(b));
    60     
    61     for(register int i=0;i<n;i++) {
    62     if(str[i] == '1') a[i] = 1;
    63     else if(str[i] == '0') b[n-i-1] = 1;
    64     }
    65     
    66     fft(a,1); fft(b,1); 
    67     for(register int i=0;i<m;i++) {
    68     f[i] += (1ll*a[i]*b[i])%mod; if(f[i] >mod)f[i]-=mod;
    69     }
    70     
    71     fft(f,-1);
    72 
    73     for(register int i=0;i<n-1;i++){
    74     int now = n-1-i;
    75     for(register int j=i-now;j>=0;j-=now){
    76         f[i] |= f[j];
    77     }
    78     }
    79 
    80     long long ans = 0;
    81     for(register int i=1;i<=n;i++){
    82     ans ^= (1ll*(f[i-1]==0)*i*i);
    83     }
    84     printf("%lld",ans);
    85 }
    86 
    87 int main(){
    88     scanf("%s",str);
    89     work();
    90     return 0;
    91 }
  • 相关阅读:
    给下拉框加上可输入查询特性-升级版本
    手把手教你在CentOS7中安装JavaJDK和配置环境变量
    CentOS7.0下MySql的安装和配置
    CentOS常规辅助工具安装
    MongoDB教程之常用操作
    商城商品超卖处理
    微信JS-SDK分享的坑
    当数据库做了Aways on后,收缩数据库日志文件
    SQL Server 2016 非域Aways On环境搭建
    win8以上系统查看iis网站进程内存占用情况
  • 原文地址:https://www.cnblogs.com/Menhera/p/9171962.html
Copyright © 2020-2023  润新知