• [ICPC2022Macau]Pass the Ball!【双模术NTT】【分块】


    分析:看到$\sum i*b_i$的式子以及每次传球向右移动一位,很容易想到HNOI2017项链的循环卷积。假设我们用FFT处理出来了每个环传0次,传1次,传2次,...,传环的大小n-1次对应的结果。那么对于每个询问k,只需要对于每个环,找出k模环的大小对应的答案即可。但是如果对每个环都找,时间复杂度是吃不消的。所以采用分块的方法,对于小于$\sqrt(n)$的环,把答案加进一个预处理数组中,对于大于$\sqrt(n)$的环,直接枚举所有询问,把结果加进去。最后再对每个询问枚举小于$\sqrt(n)$的环的累计答案。

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 
      4 const int maxn = 102000;
      5 const int mod1 = 998244353;
      6 const int mod2 = 1004535809;
      7 
      8 int n,m,num;
      9 int p[maxn],vis[maxn],query[maxn];
     10 vector<int> vec;
     11 vector<int> ans1[500]; // xiaoyu sqrtn de daan
     12 vector<int> ans2[500];
     13 
     14 int res1[maxn],res2[maxn]; //zuizhongdaan
     15 
     16 int A[maxn*16],B[maxn*16],C[maxn*16];
     17 int r[maxn*16],len = 1,bit=0;
     18 void build_P(){
     19     for(int i=0;i<9*num;i++) A[i] = B[i] = C[i] = 0;
     20     for(int i=0;i<num;i++) A[num-i-1] = vec[i];
     21     for(int i=0;i<num;i++) B[i] = B[num+i] = vec[i];
     22 }
     23 
     24 int fast_pow(int dt,int pw,int mod){
     25     int res=1,now=dt,p=1;
     26     while(p<=pw){
     27     if(p&pw) res = 1ll*res*now%mod;
     28     now=1ll*now*now%mod;
     29     p<<=1;
     30     }
     31     return res;
     32 }
     33 
     34 void FFT(int *a,int flag,int mod){
     35     for(int i=0;i<len;i++) if(i < r[i]) swap(a[i],a[r[i]]);
     36     for(int mid = 1;mid<len;mid<<=1){
     37     int nw = fast_pow(3,(mod-1)/(2*mid),mod);
     38     if(flag == -1) nw = fast_pow(nw,mod-2,mod);
     39     for(int i=0;i<len;i+=(mid<<1)){
     40         int tmp = 1;
     41         for(int j=0;j<mid;j++,tmp=1ll*tmp*nw%mod){
     42         int x = a[i+j],y=1ll*tmp*a[i+j+mid]%mod;
     43         a[i+j]=(x+y)%mod,a[i+j+mid]=(x-y+mod)%mod;
     44         }
     45     }
     46     }
     47     if(flag == -1){
     48     int dt = fast_pow(len,mod-2,mod);
     49     for(int i=0;i<len;i++){
     50         a[i] = 1ll*a[i]*dt%mod;
     51     }
     52     }
     53 }
     54 
     55 void fft(int mod){
     56     len = 1,bit = 0;
     57     while(len < 4*num){len<<=1,bit++;}
     58     for(int i=0;i<len;i++) r[i] = (r[i>>1]>>1)|((i&1)<<(bit-1));
     59     FFT(A,1,mod); FFT(B,1,mod);
     60     for(int i=0;i<len;i++) C[i] = 1ll*A[i]*B[i]%mod;
     61     FFT(C,-1,mod);
     62 }
     63 
     64 long long xxx,yyy;
     65 void exgcd(int a,int b){
     66     if(!b){
     67     xxx=1;yyy=0;return;
     68     }
     69     exgcd(b,a%b);
     70     long long t = xxx; xxx = yyy; yyy = t-a/b*yyy;
     71 }
     72 
     73 long long fast_mul(long long dt,long long pw,long long mod){
     74     long long res=0,now=dt,p=1;
     75     while(p<=pw){
     76     if(p&pw) res = (res+now)%mod;
     77     now=(now+now)%mod;
     78     p<<=1;
     79     }
     80     return res;
     81 }
     82 
     83 long long merge(int b,int d){
     84     long long mod = 1ll*mod1*mod2;
     85     long long as;
     86     if(d-b > 0){
     87     as = fast_mul(fast_mul(xxx,(d-b),mod),mod1,mod)+b;
     88     as %= mod;
     89     as += mod; as%= mod;
     90     }else{
     91     long long xx = -xxx;
     92     as = fast_mul(fast_mul(xx,b-d,mod),mod1,mod)+b;
     93     as %= mod;
     94     as += mod; as%= mod;
     95     }
     96     return as;
     97 }
     98 
     99 int main(){
    100     //freopen("1.in","r",stdin);
    101     ios::sync_with_stdio(false);
    102     cin >> n >> m;
    103     for(int i=1;i<=n;i++){
    104     cin >> p[i];
    105     }
    106     for(int i=1;i<=m;i++) cin >> query[i];
    107     
    108     for(int i=1;i*i<=n;i++){
    109     for(int j=0;j<i;j++) ans1[i].push_back(0),ans2[i].push_back(0);
    110     }
    111     
    112     for(int i=1;i<=n;i++){
    113     if(!vis[i]){
    114         int j = i;vec.clear();num = 0;
    115         while(!vis[j]){num++;vec.push_back(j);vis[j]=1;j = p[j];}
    116         build_P();
    117         fft(mod1);
    118         if(num*num <= n){
    119         for(int j=0;j<num;j++){
    120             ans1[num][j]+=C[num-1+j];
    121             ans1[num][j]%=mod1;
    122         }
    123         }else{
    124         for(int j=1;j<=m;j++){
    125             int dt = query[j]%num;
    126             res1[j] += C[num-1+dt];
    127             res1[j]%=mod1;
    128         }
    129         }
    130         build_P();
    131         fft(mod2);
    132         if(num*num <= n){
    133         for(int j=0;j<num;j++){
    134             ans2[num][j]+=C[num-1+j];
    135             ans2[num][j]%=mod2;
    136         }
    137         }else{
    138         for(int j=1;j<=m;j++){
    139             int dt = query[j]%num;
    140             res2[j] += C[num-1+dt];
    141             res2[j]%=mod2;
    142         }
    143         }
    144     }
    145     }
    146     for(int i=2;i*i<=n;i++){
    147     for(int j=1;j<=m;j++){
    148         res1[j] += ans1[i][query[j]%i];
    149         res1[j]%=mod1;
    150         res2[j] += ans2[i][query[j]%i];
    151         res2[j]%=mod2;
    152     }
    153     }
    154     exgcd(mod1,mod2);
    155     for(int i=1;i<=m;i++){
    156     //cout<<res1[i]<<" "<<res2[i]<<endl;
    157     cout<<merge(res1[i],res2[i])<<endl;
    158     }
    159     return 0;
    160 }
  • 相关阅读:
    OCP-1Z0-052-V9.02-177题
    游戏服务端IOCP模型,自己封装的一个类,3行代码搞定服务端。
    OCP-1Z0-052-V9.02-116题
    OCP-1Z0-052-V9.02-72题
    map按value值查找——find_if的使用
    Oracle OCP 11G 052答案解析目录
    Oracle OCP 11G 052 V8.02与V9.02版本对比
    OCP-1Z0-052-V8.02-102题
    OCP-1Z0-052-V8.02-117题
    在完成端口IOCP模型判断客户端是否已关闭连接(掉线)
  • 原文地址:https://www.cnblogs.com/Menhera/p/16114894.html
Copyright © 2020-2023  润新知