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\n", (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\n", (1LL << (n-r)) - 1);

68     }

69 

70     return 0;

71 }
代码君

 

你可能感兴趣的:(uva)