• CQOI2018 九连环 打表找规律 fft快速傅里叶变换


    题面:

      CQOI2018九连环

    分析:

      个人认为这道题没有什么价值,纯粹是为了考算法而考算法。

      对于小数据我们可以直接爆搜打表,打表出来我们可以观察规律。

      f[1~10]: 1 2 5 10 21 42 85 170 341 682

      我们可以发现的规律是,当i为奇数时,f[i]=f[i-1]*2+1,偶数时f[i]=f[i-1]*2。

      既然这样,我们可以推断通项公式是否跟2的次幂有关。

      我们连蒙带猜连导带推,可以得出,f[i]=2^(i+1)/3(下取整)。

      再结合数据范围,我们可以决定是写fft+快速幂还是写python

      这样这道题就结束了。

    代码:

     1 #include<bits/stdc++.h>
     2 #define db double
     3 #define ll long long
     4 #define cp complex<db>
     5 using namespace std;
     6 const int N=70000;
     7 const db pi=acos(-1);int r[N];
     8 void fft(cp *a,int *r,int lm,int op){
     9     for(int i=0;i<lm;i++) 
    10     if(i<r[i]) swap(a[i],a[r[i]]);
    11     for(int mid=1;mid<lm;mid<<=1){
    12         cp wn;wn=cp(cos(pi/mid),op*sin(pi/mid));
    13         for(int R=mid<<1,j =0;j<lm;j+=R){
    14             cp w;w=cp(1,0);
    15             for(int k=0;k<mid;k++,w=w*wn){
    16                 cp x=a[j+k],y=w*a[j+mid+k];
    17                 a[j+k]=x+y;a[j+mid+k]=x-y;
    18             }
    19         }
    20     } return ;
    21 } struct big{
    22     int g[N],len;
    23     big(){
    24         memset(g,0,sizeof(g));len=1;
    25     } big(int x){
    26         memset(g,0,sizeof(g));len=0;
    27         if(!x){len=1;return ;}
    28         while(x) g[len++]=x%10,x/=10;
    29     } void operator *=(const big &b){
    30         static cp A[N],B[N];
    31         int nl=len+b.len,lm=1,L=0;
    32         while(lm<nl) lm<<=1,++L;
    33         for(int i=0;i<lm;i++)
    34         A[i]=cp(i<len?g[i]:0,0),
    35         B[i]=cp(i<b.len?b.g[i]:0,0);r[0]=0;
    36         for(int i=0;i<lm;i++)
    37         r[i]=(r[i>>1]>>1)|((i&1)<<(L-1));
    38         fft(A,r,lm,1);fft(B,r,lm,1);
    39         for(int i=0;i<lm;i++) A[i]*=B[i];
    40         fft(A,r,lm,-1);int ans[N];
    41         for(int i=0;i<lm;i++)
    42         ans[i]=(int)(A[i].real()/lm+0.5);
    43         for(int i=0;i<lm;i++)
    44         if(ans[i]>9) ans[i+1]+=ans[i]/10,
    45         ans[i]%=10;lm--;
    46         while(lm>0&&!ans[lm]) lm--;len=++lm;
    47         for(int i=0;i<lm;i++) g[i]=ans[i];
    48     } void operator /= (int x){
    49         int sm=0,nl=0;
    50         for(int i=len-1;~i;i--){
    51             sm=sm*10+g[i];
    52             if(sm<x) g[i]=0;
    53             else{
    54                 if(!nl) nl=i+1;
    55                 g[i]=sm/x,sm%=x;
    56             }
    57         } len=max(nl,1);
    58     } void print(){
    59         for(int i=len-1;~i;i--)
    60         printf("%d",g[i]);puts("");
    61     }
    62 }ret,bs;
    63 int main(){
    64     int t;scanf("%d",&t);while(t--){
    65         int n;scanf("%d",&n);n++;
    66         ret=big(1);bs=big(2);
    67         while(n){
    68             if(n&1) ret*=bs;
    69             bs*=bs;n>>=1;
    70         } ret/=3;ret.print();
    71     } return 0;
    72 }
    fft快速傅里叶变换
  • 相关阅读:
    Java多线程系列--“基础篇”11之 生产消费者问题
    Java多线程系列--“基础篇”10之 线程优先级和守护线程
    Java多线程系列--“基础篇”09之 interrupt()和线程终止方式
    Java多线程系列--“基础篇”08之 join()
    Java四种线程池的使用
    数据库索引的实现原理
    Java多线程系列--“基础篇”07之 线程休眠
    Java多线程系列--“基础篇”06之 线程让步
    Java多线程系列--“基础篇”05之 线程等待与唤醒
    Java多线程系列--“基础篇”04之 synchronized关键字
  • 原文地址:https://www.cnblogs.com/Alan-Luo/p/10414139.html
Copyright © 2020-2023  润新知