# 【构造 meet in middle 随机 矩阵树定理】#75. 【UR #6】智商锁

没智商了

## 题目分析

  1 #include<bits/stdc++.h>
2 #define MO 998244353
3 const int maxn = 54;
4 const int maxm = 20003;
5
6 int qmi(int a, int b)
7 {
8     int ret = 1;
9     for (; b; b>>=1,a=1ll*a*a%MO)
10         if (b&1) ret = 1ll*ret*a%MO;
11     return ret;
12 }
13 std::set<int> gcnt;
14 struct Graph
15 {
16     int n,m,val;
17     int fa[maxn],f[maxn][maxn],deg[maxn];
18     bool mp[maxn][maxn];
19
20     Graph(){memset(mp, 0, sizeof mp);}
21     int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
22     int Gauss(int n)
23     {
24         int ret = 1;
25         for (int i=1; i<=n; i++)
26         {
27             if (!f[i][i]) return 0;
28             for (int j=i+1; j<=n; j++)
29                 if (f[j][i]){
30                     int det = 1ll*f[j][i]*qmi(f[i][i], MO-2)%MO;
31                     for (int k=i; k<=n; k++)
32                         f[j][k] = (f[j][k]-1ll*f[i][k]*det%MO+MO)%MO;
33                 }
34         }
35         for (int i=1; i<=n; i++)
36             ret = 1ll*ret*f[i][i]%MO;
37         return ret;
38     }
39     void output(int det)
40     {
41         for (int p=1; p<=n; p++)
42             for (int t=p+1; t<=n; t++)
43                 if (mp[p][t]) printf("%d %d\n",p+det,t+det);
44     }
45     void random(int Range)
46     {
47         val = 1;
48         do{
49             memset(f, 0, sizeof f);
50             memset(mp, 0, sizeof mp);
51             n = rand()%Range+1, m = std::min(n-1+rand()%(n*(n-1)/2-n+10), n*(n-1)/2);
52             for (int i=1; i<=n; i++) fa[i] = i;
53             for (int i=1; i<n; i++)
54             {
55                 int u = rand()%n+1, v = rand()%n+1;
56                 while (find(u)==find(v))
57                     u = rand()%n+1, v = rand()%n+1;
58                 fa[fa[u]] = fa[v];
59                 mp[u][v] = mp[v][u] = true;
60                 f[u][v] = f[v][u] = MO-1;
61                 ++f[u][u], ++f[v][v];
62             }
63             for (int i=n; i<=m; i++)
64             {
65                 int u = rand()%n+1, v = rand()%n+1;
66                 while (mp[u][v]||v==u)
67                     u = rand()%n+1, v = rand()%n+1;
68                 mp[u][v] = mp[v][u] = true;
69                 f[u][v] = f[v][u] = MO-1;
70                 ++f[u][u], ++f[v][v];
71             }
72             for (int i=1; i<=n; i++)
73                 for (int j=1; j<=n; j++)
74                     if (f[i][j] < 0) f[i][j] += MO;
75             val = Gauss(n-1);
76         }while (gcnt.count(val));
77         gcnt.insert(val);
78     }
79 }f[1335];
80 struct node
81 {
82     int idx,idy,val;
83     bool operator < (node a) const
84     {
85         return val < a.val;
86     }
87 }ddc[1000035];
88 int T,n,tot;
89 bool legal;
90
91 void init()
92 {
93     srand(time(0));
94     f[1].n = f[1].val = 1, gcnt.insert(1);
95     f[2].n = f[2].val = 1, gcnt.insert(1);
96     f[3].n = f[3].val = 1, gcnt.insert(1);
97     for (int i=4; i<=500; i++) f[i].random(20);
98     for (int i=501; i<=1200; i++) f[i].random(50);
99     for (int i=1; i<=600; i++)
100         for (int j=i+1; j<=600; j++)
101             ddc[++tot].val = 1ll*f[i].val*f[j].val%MO,
102             ddc[tot].idx = i, ddc[tot].idy = j;
103     std::sort(ddc+1, ddc+tot+1);
104 }
105 void output(int id1, int id2, int id3, int id4)
106 {
107     int det = 0;
108     int n1 = f[id1].n, n2 = f[id2].n, n3 = f[id3].n, n4 = f[id4].n;
109     if (n1+n2+n3+n4 > 100) return;
110     printf("%d %d\n",n1+n2+n3+n4,f[id1].m+f[id2].m+f[id3].m+f[id4].m+3);
111     f[id1].output(det), det += n1, printf("1 %d\n",det+1);
112     f[id2].output(det), det += n2, printf("1 %d\n",det+1);
113     f[id3].output(det), det += n3, printf("1 %d\n",det+1);
114     f[id4].output(det), det += n4;
115     legal = true;
116 }
117 int main()
118 {
119     init();
120     for (scanf("%d",&T); T; --T)
121     {
122         scanf("%d",&n), legal = false;
123         if (n==0){
124             puts("2 0");continue;
125         }
126         for (int i=601; i<=1200&&!legal; i++)
127             for (int j=i+1; j<=1200&&!legal; j++)
128             {
129                 int trans = 1ll*n*qmi(1ll*f[i].val*f[j].val%MO, MO-2)%MO;
130                 int L = 1, R = tot, pos = -1;
131                 for (int mid=(L+R)>>1; L<=R; mid=(L+R)>>1)
132                     if (ddc[mid].val <= trans) pos = mid, L = mid+1;
133                     else R = mid-1;
134                 if (ddc[pos].val==trans)
135                     output(ddc[pos].idx, ddc[pos].idy, i, j);
136             }
137         if (!legal) puts("QwQ");
138     }
139     return 0;
140 }

END

posted @ 2019-07-12 11:11  AntiQuality  阅读(218)  评论(0编辑  收藏  举报