8.9日总结

题赛地址


C题:(三元环计数) 
题意,给定一个图,求四元环的个数,这个四元环要求是由两个三元环相邻一条共同边组成的

解法: 
①统计每个点的度数 
②入度<=sqrt(m)的分为第一类,入度>sqrt(m)的分为第二类 
③对于第一类,暴力每个点,然后暴力这个点的任意两条边,再判断这两条边的另一个端点是否连接 
因为m条边最多每条边遍历一次,然后暴力的点的入度<=sqrt(m),所以复杂度约为O(msqrt(m)) 
④对于第二类,直接暴力任意三个点,判断这三个点是否构成环,因为这一类点的个数不会超过sqrt(m)个,所以复杂度约为O(sqrt(m)3)=O(msqrt(m)) 
⑤判断两个点是否连接可以用set,map和Hash都行,根据具体情况而行 
这种做法建的是双向边,常数很大

 1 //https://www.cnblogs.com/jiachinzhao/p/7474761.html
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<set>
 5 #include<cmath>
 6 #include<vector>
 7 using namespace std;
 8 typedef long long ll;
 9 const int maxn = 1e5 + 10;
10 set<ll>s;
11 int deg[maxn];
12 vector<int>g[maxn];
13 int vis[maxn], vi[maxn];
14 
15 int main() {
16     int n, m, u, v, sz;
17     while (scanf("%d%d", &n, &m) != EOF) {
18         sz = sqrt(m + 0.5);
19         s.clear();
20         for (int i = 1; i <= n; i++) {
21             vis[i] = vi[i] = deg[i] = 0;
22             g[i].clear();
23         }
24         for (int i = 0; i < m; i++) {
25             scanf("%d%d", &u, &v);
26             s.insert(u + 1ll * v*n);
27             s.insert(v + 1ll * u*n);
28             deg[u]++, deg[v]++;
29             g[u].push_back(v); g[v].push_back(u);
30         }
31         ll ans = 0;
32         for (int u = 1; u <= n; u++) {
33             vis[u] = 1;
34             for (auto v : g[u])vi[v] = u;
35             for (auto v : g[u]) {
36                 int cnt = 0;
37                 if (vis[v])continue;
38                 if (deg[v] <= sz) {
39                     for (auto vv : g[v])
40                         if (vi[vv] == u)cnt++;
41                 }
42                 else {
43                     for (auto vv : g[u]) {
44                         if (s.find(1ll * v*n + vv) != s.end())cnt++;
45                     }
46                 }
47                 ans += 1ll * cnt*(cnt - 1) / 2;
48             }
49         }
50         printf("%lld
", ans);
51     }
52     return 0;
53 }

D(矩阵快速幂) 
题意:有一个4*n的矩阵,要求只能只能用2x1的木板覆盖,问一共有多少种覆盖的方法

解法: 
当前一列已经铺满的时候,那么下一列一共有五种铺法,根据这五种铺发推出递推关系式,之后矩阵快速幂跑一下即可 
博客链接

 1 //https://blog.csdn.net/elbadaernu/article/details/77825979
 2 
 3 #include <iostream> 
 4 #include <cstring>
 5 #include <cstdio>
 6 using namespace std;
 7 #define LL long long 
 8 const int mod = 1000000007;
 9 struct matrix
10 {
11     LL x[4][4];
12 };
13 matrix mutimatrix(matrix a, matrix b)
14 {
15     matrix temp;
16     memset(temp.x, 0, sizeof(temp.x));
17     for (int i = 0; i < 4; i++)
18         for (int j = 0; j < 4; j++)
19             for (int k = 0; k < 4; k++)
20             {
21                 temp.x[i][j] += a.x[i][k] * b.x[k][j];
22                 temp.x[i][j] %= mod;
23             }
24     return temp;
25 }
26 
27 matrix k_powmatrix(matrix a, LL n)//矩阵快速幂
28 {
29     matrix temp;
30     memset(temp.x, 0, sizeof(temp.x));
31     for (int i = 0; i < 4; i++)
32         temp.x[i][i] = 1;
33 
34     while (n)
35     {
36         if (n & 1)
37             temp = mutimatrix(temp, a);
38 
39         a = mutimatrix(a, a);
40         n >>= 1;
41     }
42     return temp;
43 }
44 
45 
46 int main(){
47     LL n;
48     while (scanf("%lld", &n) != EOF){
49         //前面四个手算下
50         if (n == 1){printf("1
");continue;}
51         if (n == 2){printf("5
");continue;}
52         if (n == 3){printf("11
");continue;}
53         if (n == 4){printf("36
");continue;}
54 
55         matrix st;
56         memset(st.x, 0, sizeof(st.x));
57         st.x[0][0] = 1;
58         st.x[1][0] = 5;
59         st.x[2][0] = 1;
60         st.x[3][0] = -1;
61 
62         st.x[0][1] = 1;
63         st.x[1][2] = 1;
64         st.x[2][3] = 1;
65 
66         matrix init;//初始矩阵
67         memset(init.x, 0, sizeof(init.x));
68 
69         init.x[0][0] = 36;
70         init.x[0][1] = 11;
71         init.x[0][2] = 5;
72         init.x[0][3] = 1;
73 
74         st = k_powmatrix(st, n - 4);//经过n-4次相乘
75         st = mutimatrix(init, st);//然后再乘上初始矩阵
76 
77         printf("%lld
", (st.x[0][0] + mod) % mod);
78     }
79     return 0;
80 }
 

E: 
题意: 
有一列数,每次询问随机的删掉一个数,求最后所有数且、或、异或的结果

解法: 
按位处理,每一位统计一的个数,之后按一的个数为0,为1,为n,以及其他情况分类讨论即可

 1 #include<cstdio>
 2 #include<cstring>
 3 using namespace std;
 4 const int maxn = 1e6 + 5;
 5 
 6 int n, m;
 7 int a[maxn];
 8 int b[maxn];
 9 
10 int main() {
11     while (~scanf("%d %d", &n, &m)) {
12         memset(a, 0, sizeof(a)); 
13         memset(b, 0, sizeof(b));
14 
15         int AND = 0, OR = 0, XOR = 0;
16         for (int i = 1; i <= n; i++) {
17             scanf("%d", &a[i]);
18             int t = a[i], k = 0;
19             XOR ^= a[i];
20             while (t) { b[k++] += t % 2; t /= 2; }
21         }
22 
23         while (m--){
24             int x; scanf("%d", &x);
25             x = a[x];
26             int NXOR = XOR^x;
27             AND = 0, OR = 0;
28             for (int j = 0; j < 32; j++) {
29                 if (b[j] == 0)continue;
30                 else if (b[j] == 1) {
31                     if (x&(1 << j))continue;
32                     OR += (1 << j);
33                     if (n == 2)AND += (1 << j);
34                 }
35                 else if (b[j] == n) {
36                     AND += (1 << j); OR += (1 << j);
37                 }
38                 else {
39                     OR += (1 << j);
40                     if (b[j] == n - 1 && !(x&(1 << j)))
41                         AND += (1 << j);
42                 }
43             }
44             printf("%d %d %d
", AND, OR, NXOR);
45         }
46     }
47     return 0;
48 }

H:(打表+数论) 
题意: 
给定一个数n和a,问在 [1,1 << n] 的范围内有多少个b满足 a^b=b^a(mod 1 << n)

解法: 
关键是思路! 

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<string>
 5 #include<string>
 6 #include<cmath>
 7 #include<stack>
 8 #include<vector>
 9 #include<queue>
10 #include<algorithm>
11 using namespace std;
12 const int MAXM=100010;
13 const long long MOD=1000000007;
14 const double PI=acos(-1);
15 
16 long long n,a;
17 
18 long long qpow(long long x,long long y,long long mod)
19 {
20     long long res=1;
21     while(y)
22     {
23         if (y&1) res=(res*x)%mod;
24         x=(x*x)%mod;
25         y=y>>1;
26     }
27     return res;
28 }
29 long long qpow(long long x,long long y)
30 {
31     long long res=1;
32     while(y)
33     {
34         if (y&1) res=res*x;
35         x=x*x;
36         y=y>>1;
37     }
38     return res;
39 }
40 int main()
41 {
42     while(scanf("%lld%lld",&n,&a)!=EOF)
43     {
44         if (a&1)
45         {
46             printf("1
");
47             continue;
48         }
49         else
50         {
51             long long m=1<<n;
52             long long ans=0;
53             for (long long i=1;i<=n;i++)
54                 if (qpow(a,i,m)==qpow(i,a,m))
55                 ans++;
56             long long b2=n/a;
57             if (b2*a<n) b2=b2+1;
58             long long b3=qpow(2,b2);
59             //int b4=qpow(2,a);
60             long long res=m/b3-n/b3;
61             ans=ans+res;
62             printf("%lld
",ans);
63         }
64     }
65     return 0;
66 }
67  
原文地址:https://www.cnblogs.com/romaLzhih/p/9489793.html