zoukankan      html  css  js  c++  java
  • [loj3330]猜数游戏

    如果两个数$a_{x}$和$a_{y}$,$exists 0<i,a_{x}^{i}equiv a_{y}(mod p^{k})$,就建一条$x$到$y$的有向边,再对这张图强连通分量缩点,记$s_{i}$表示第$i$个点的大小,$f_{i}$表示能到达$i$的点(初始)数量,则答案为$sum_{i=1}^{scc}frac{2^{s_{i}}-1}{2^{s_{i}+f_{i}}}$(对每一个点分别统计贡献)
    问题就变为如何判定$exists i,x^{i}equiv y(mod p^{k})$,分为$pmid x$和$p mid x$两类
    对于$xmid p$和$y mid p$,$x^{i}equiv y(mod p^{k})$的必要条件为$x^{i}equiv y(mod p)$,而$x^{i}equiv 0 e y(mod p)$(交换$x$和$y$也同理可以证明),因此两类之间没有关系
    对于$xmid p$和$ymid p$,必然有$forall kle i,x^{i}equiv 0(mod p^{k})$,暴力枚举$i$即可,时间复杂度$o(nlog p)$
    对于$x mid p$和$y mid p$,如果求出$且ord(x)=min_{i>0且x^{i}equiv 1(mod p^{k})}i$,那么$x^{i}equiv y(mod p^{k})$当且仅当$ord(y)mid ord(x)$
    用BSGS求$ord(x)$复杂度及常数较大,考虑$ord(x)mid varphi(p)$,枚举$varphi(p)$的质因子并判断能否消除,复杂度为$o(nlog^{2}p)$
     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define N 5005
     4 #define mod 998244353
     5 map<int,int>mat;
     6 vector<int>v,v1[N],v2[N],v3[N];
     7 int n,m,P,p,k,ans,a[N],ord[N],vis[N],dfn[N],sz[N],bl[N],dp[N];
     8 int ksm(int n,int m,int p){
     9     if (!m)return 1;
    10     int s=ksm(n,m>>1,p);
    11     s=1LL*s*s%p;
    12     if (m&1)s=1LL*s*n%p;
    13     return s; 
    14 }
    15 int bsgs(int k){
    16     int ans=1;
    17     for(int i=0;i<v.size();i++)ans=ans*v[i];
    18     for(int i=0;i<v.size();i++)
    19         if (ksm(k,ans/v[i],P)==1)ans/=v[i];
    20     return ans;
    21 }
    22 void add(int x,int y){
    23     v1[x].push_back(y);
    24     v2[y].push_back(x);
    25 }
    26 void dfs1(int k){
    27     if (vis[k])return;
    28     vis[k]=1;
    29     for(int i=0;i<v1[k].size();i++)dfs1(v1[k][i]);
    30     dfn[++dfn[0]]=k;
    31 }
    32 void dfs2(int k){
    33     if (bl[k]){
    34         if (bl[k]!=m)v3[m].push_back(bl[k]);
    35         return;
    36     }
    37     sz[m]++;
    38     bl[k]=m;
    39     for(int i=0;i<v2[k].size();i++)dfs2(v2[k][i]);
    40 }
    41 void dfs3(int k,int x){
    42     if (vis[k])return;
    43     vis[k]=1;
    44     dp[x]+=sz[k];
    45     for(int i=0;i<v3[k].size();i++)dfs3(v3[k][i],x);
    46 }
    47 void init(){
    48     p=P;
    49     for(int i=3;i*i<=P;i++)
    50         if (P%i==0){
    51             p=i;
    52             break;
    53         }
    54     for(int i=P;i>1;i/=p)k++;
    55     int j=P/p*(p-1);
    56     for(int i=2;i*i<=j;i++)
    57         while (j%i==0){
    58             j/=i;
    59             v.push_back(i);
    60         }
    61     if (j>1)v.push_back(j);
    62 }
    63 void Kosaraju(){
    64     memset(vis,0,sizeof(vis));
    65     for(int i=1;i<=n;i++)dfs1(i);
    66     for(int i=n;i;i--)
    67         if (!bl[dfn[i]]){
    68             m++;
    69             dfs2(dfn[i]);
    70         }
    71 }
    72 int main(){
    73     scanf("%d%d",&n,&P);
    74     init();
    75     for(int i=1;i<=n;i++){
    76         scanf("%d",&a[i]);
    77         mat[a[i]]=i;
    78     }
    79     for(int i=1;i<=n;i++)
    80         if (a[i]%p)ord[i]=bsgs(a[i]);
    81         else{
    82             for(int j=1,t=a[i];t>0;j++,t=1LL*t*a[i]%P)
    83                 if ((mat[t])&&(mat[t]!=i))add(i,mat[t]);
    84         }
    85     for(int i=1;i<=n;i++)
    86         for(int j=1;j<=n;j++)
    87             if ((i!=j)&&(ord[i])&&(ord[j])&&(ord[i]%ord[j]==0))add(i,j);
    88     Kosaraju();
    89     for(int i=1;i<=m;i++){
    90         memset(vis,0,sizeof(vis));
    91         dfs3(i,i);
    92     }
    93     for(int i=1;i<=n;i++)ans=(ans+(ksm(2,sz[i],mod)-1LL)*ksm(2,n-dp[i],mod))%mod;
    94     printf("%d",ans);
    95     return 0;
    96 }
    View Code
  • 相关阅读:
    vue Bus事件用法与bug
    移动端超出三行显示第三行显示省略号+查看全部
    Vuex
    vue点击旋转,再点击复原
    vue项目(cli-3)替换浏览器logo
    悬浮广告(二)vue版本
    悬浮广告(一)html版本
    vue下获得经纬度省市区
    一个可以输出当前移动设备机型(安卓,ios)系统版本的html页面
    谱聚类(spectral clustering)原理总结
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/13502682.html
Copyright © 2011-2022 走看看