• UVa 11542 (高斯消元 异或方程组) Square


    书上分析的太清楚,我都懒得写题解了。=_=||

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <cmath>
     4 #include <algorithm>
     5 using namespace std;
     6 
     7 const int maxp = 100;
     8 const int maxn = 500;
     9 bool vis[maxn + 10];
    10 int prime[maxp], pcnt = 0;
    11 
    12 void Init()
    13 {
    14     int m = sqrt(maxn + 0.5);
    15     for(int i = 2; i <= m; i++) if(!vis[i])
    16         for(int j = i*i; j <= maxn; j += i) vis[j] = true;
    17     for(int i = 2; i <= maxn; i++) if(!vis[i]) prime[pcnt++] = i;
    18 }
    19 
    20 typedef int Matrix[maxn][maxn];
    21 
    22 Matrix A;
    23 
    24 int rank(Matrix A, int m, int n)
    25 {//求系数矩阵A的秩,m个方程,n个未知数
    26     int i = 0, j = 0;
    27     while(i < m && j < n)
    28     {
    29         int r = i, k;
    30         for(k = r; k < m; k++) if(A[k][j]) { r = k; break; }
    31         if(k < m)
    32         {
    33             if(r != i) for(int k = 0; k < n; k++) swap(A[r][k], A[i][k]);
    34             for(int k = i+1; k < m; k++) if(A[k][j])
    35                 for(int l = j; l < n; l++) A[k][l] ^= A[i][l];
    36             i++;
    37         }
    38         j++;
    39     }
    40     return i;
    41 }
    42 
    43 int main()
    44 {
    45     //freopen("in.txt", "r", stdin);
    46 
    47     Init();
    48     int T;
    49     scanf("%d", &T);
    50     while(T--)
    51     {
    52         memset(A, 0, sizeof(A));
    53         int n, M = 0;
    54         scanf("%d", &n);
    55         for(int i = 0; i < n; i++)
    56         {
    57             long long x;
    58             scanf("%lld", &x);
    59             for(int j = 0; j < pcnt; j++) while(x % prime[j] == 0)
    60             {
    61                 M = max(M, j);
    62                 x /= prime[j];
    63                 A[j][i] ^= 1;
    64             }
    65         }
    66         int r = rank(A, M+1, n);//共用到前M+1个素数
    67         printf("%lld
    ", (1LL << (n-r)) - 1);
    68     }
    69 
    70     return 0;
    71 }
    代码君

    最后lrj老师提到了还可以用状压加速消元,因为500以内的素数不超过100个,所以我用了两个64位的long long来表示一个方程。第一份代码16ms,状压以后12ms,快了四分之一。

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <cmath>
     4 #include <algorithm>
     5 using namespace std;
     6 
     7 const int maxp = 100;
     8 const int maxn = 500;
     9 bool vis[maxn + 10];
    10 int prime[maxp], pcnt = 0;
    11 
    12 void Init()
    13 {
    14     int m = sqrt(maxn + 0.5);
    15     for(int i = 2; i <= m; i++) if(!vis[i])
    16         for(int j = i*i; j <= maxn; j += i) vis[j] = true;
    17     for(int i = 2; i <= maxn; i++) if(!vis[i]) prime[pcnt++] = i;
    18 }
    19 
    20 typedef long long Matrix[maxn][2];
    21 
    22 Matrix A;
    23 
    24 int rank(Matrix A, int m, int n)
    25 {//求系数矩阵A的秩,m个方程,n个未知数
    26     int i = 0, j = 0, len = n / 64;
    27     while(i < m && j < n)
    28     {
    29         int r = i, k;
    30         for(k = r; k < m; k++) if(A[k][j/64] & (1LL<<(j%64))) { r = k; break; }
    31         if(k < m)
    32         {
    33             if(r != i) for(int k = 0; k <= len; k++) swap(A[r][k], A[i][k]);
    34             for(int k = i+1; k < m; k++) if(A[k][j/64] & (1LL<<(j%64)))
    35                 for(int l = 0; l <= len; l++) A[k][l] ^= A[i][l];
    36             i++;
    37         }
    38         j++;
    39     }
    40     return i;
    41 }
    42 
    43 int main()
    44 {
    45     //freopen("in.txt", "r", stdin);
    46 
    47     Init();
    48     int T;
    49     scanf("%d", &T);
    50     while(T--)
    51     {
    52         memset(A, 0, sizeof(A));
    53         int n, M = 0;
    54         scanf("%d", &n);
    55         for(int i = 0; i < n; i++)
    56         {
    57             long long x;
    58             scanf("%lld", &x);
    59             for(int j = 0; j < pcnt; j++) while(x % prime[j] == 0)
    60             {
    61                 M = max(M, j);
    62                 x /= prime[j];
    63                 A[j][i/64] ^= (1LL << (i%64) );
    64             }
    65         }
    66         int r = rank(A, M+1, n);//共用到前M+1个素数
    67         printf("%lld
    ", (1LL << (n-r)) - 1);
    68     }
    69 
    70     return 0;
    71 }
    代码君
  • 相关阅读:
    Web 2.0网站命名的7个建议
    梦猪课堂视频系列
    计算机英文术语完全介绍
    PPT高手的思路
    在线RSS阅读器大比拼
    【百度现有服务】
    转载VFW编程实例(详)
    实现MFC扩展DLL中导出类和对话框 (转)
    Windows下编译 OpenSceneGraph(转)
    OSG静态编译 (转)
  • 原文地址:https://www.cnblogs.com/AOQNRMGYXLMV/p/4338322.html
Copyright © 2020-2023  润新知