zoukankan      html  css  js  c++  java
  • noi 2007 生成树计数 矩阵乘法

    题意:
      有一个N个顶点的无向图,N个顶点编号为1~N。点i与点j之间有一条无向边当且仅当|i-j|<=k,求这个无向图的生成树个数mod 65521的值。


    思路:以连续k个点的连通情况作为状态


      1 #include<iostream>
    2 #include<map>
    3 #include<string>
    4 using namespace std;
    5 #define mod 65521
    6 long long n;
    7 int m,t,top;
    8 map <int,int> home;
    9 struct matrix
    10 {
    11 long long a[60][60];
    12 matrix(){ memset(a,0,sizeof(a)); }
    13 };
    14 matrix graph;
    15 struct Edge
    16 {
    17 int l,r;
    18 }edge[11];
    19 int c[10];
    20 int f[10],hash[100],temp[10],vector[101],used[10];
    21 bool use[11];
    22 matrix operator *(const matrix &x,const matrix &y)
    23 {
    24 int i,j,k;
    25 matrix ans;
    26 for(i=1;i<=top;i++)
    27 for(j=1;j<=top;j++)
    28 for(k=1;k<=top;k++)
    29 {
    30 ans.a[i][j]+=x.a[i][k]*y.a[k][j];
    31 if(ans.a[i][j]>=mod) ans.a[i][j]%=mod;
    32 }
    33 return ans;
    34 }
    35 int find(int x)
    36 {
    37 return f[x]==-1?x:f[x]=find(f[x]);
    38 }
    39 bool merge(int x,int y)
    40 {
    41 if(find(x)==find(y)) return 1;
    42 f[find(x)]=find(y); return 0;
    43 }
    44 void dfs(int i)
    45 {
    46 if(i==m*(m-1)/2+1)
    47 {
    48 memset(f,0xff,sizeof(f));
    49 if(t>=m) return ;
    50 int j,k,ten=1,c=0;
    51 for(j=1;j<=m*(m-1)/2;j++)
    52 if(use[j]&&merge(edge[j].l,edge[j].r)) return ;
    53 for(j=1;j<m;j++) ten*=10;
    54 for(j=1;j<=m;j++)
    55 {
    56 for(k=1;k<=j;k++)
    57 if(find(k)==find(j))
    58 {
    59 c+=k*ten; break;
    60 }
    61 ten/=10;
    62 }
    63 if(home[c]!=0) return ;
    64 home[c]=++top; hash[top]=c;
    65 return ;
    66 }
    67 dfs(i+1);
    68 use[i]=1; t++;
    69 dfs(i+1);
    70 use[i]=0; t--;
    71 }
    72 void dfs2(int i,int c[],int x)
    73 {
    74 if(i==m+1)
    75 {
    76 int j,k,ten=1,y=0,first;
    77 for(j=1;j<=m;j++) temp[j]=c[j];
    78 memset(f,0xff,sizeof(f));
    79 for(j=1;j<=m;j++) merge(j,c[j]);
    80 for(j=1;j<=m;j++)
    81 if(use[j]&&merge(c[j],m+1)) return ;
    82 for(first=2;first<=m+1;first++)
    83 if(find(1)==find(first)) break;
    84 if(first==m+2) return ;
    85
    86 if(find(m+1)==m+1) c[m+1]=m+1;
    87 else c[m+1]=c[find(m+1)];
    88 for(j=2;j<=m+1;j++)
    89 if(c[j]==1) c[j]=first;
    90
    91 for(j=1;j<m;j++) ten*=10;
    92 for(j=2;j<=m+1;j++)
    93 {
    94 for(k=2;k<=j;k++)
    95 if(find(k)==find(j))
    96 {
    97 y+=(k-1)*ten; break;
    98 }
    99 ten/=10;
    100 }
    101 for(j=1;j<=m;j++) c[j]=temp[j];
    102 graph.a[x][home[y]]++;
    103 return ;
    104 }
    105
    106 dfs2(i+1,c,x);
    107 use[i]=1;
    108 dfs2(i+1,c,x);
    109 use[i]=0;
    110 }
    111
    112 void build_matrix()
    113 {
    114 int i,j;
    115 for(i=1;i<=top;i++)
    116 {
    117 vector[i]=1;
    118 memset(use,0,sizeof(use));
    119 memset(used,0,sizeof(used));
    120 int x=hash[i];
    121 for(j=1;j<=m;j++)
    122 {
    123 c[m-j+1]=x%10; x/=10;
    124 used[c[m-j+1]]++;
    125 }
    126 for(j=1;j<=m;j++)
    127 {
    128 if(used[j]==3) vector[i]=3;
    129 if(used[j]==4) vector[i]=16;
    130 if(used[j]==5) vector[i]=125;
    131 }
    132 dfs2(1,c,i);
    133 }
    134 }
    135 int matrix_pow()
    136 {
    137 n=n-m;
    138 int i,j;
    139 int des=0,ten=1;
    140 for(i=1;i<=m;i++)
    141 {
    142 des+=ten;
    143 ten=ten*10;
    144 }
    145 matrix ans;
    146 for(i=1;i<=top;i++) ans.a[i][i]=1;
    147 while(n>0)
    148 {
    149 if(n&1) ans=ans*graph;
    150 graph=graph*graph;
    151 n>>=1;
    152 }
    153 int sum=0;
    154 for(i=1;i<=top;i++) sum+=vector[i]*ans.a[i][home[des]];
    155 return sum%mod;
    156 }
    157 int main()
    158 {
    159 freopen("count.in","r",stdin);
    160 freopen("count.out","w",stdout);
    161 memset(use,0,sizeof(use));
    162 cin>>m>>n;
    163 int i,j;
    164 top=0;
    165 for(i=1;i<=m;i++)
    166 for(j=i+1;j<=m;j++)
    167 {
    168 edge[++top].l=i; edge[top].r=j;
    169 }
    170 top=t=0;
    171 dfs(1);
    172 build_matrix();
    173 cout<<matrix_pow()<<endl;
    174 return 0;
    175 }



  • 相关阅读:
    [linux]在使用rsync时需要注意的小细节
    [日期工具分享][Shell]为特定命令依次传入顺序日期执行
    【API】反转输入字符(Java)
    【笔记】对自定义异常的理解(Java)
    【技巧】解决win10的1803版本下,无法收到1809推送、从而无法更新到1903版本的问题。
    【杂谈】5G有啥用?跟咱有关系么?关注那玩意儿干啥?
    【练习总结】题目:筛法遍历素数(Java)
    【练习】Java实现的杨辉三角形控制台输出
    windows系列的(xp/win7/server2003/2008/2012...)完美移植到centos7下面的虚拟机(KVM)
    模块之-os模块
  • 原文地址:https://www.cnblogs.com/myoi/p/2389505.html
Copyright © 2011-2022 走看看