[NOIP2004]虫食算 高斯消元
2014-12-02 00:07
225 查看
网上的题解各种坑 真是尴尬 搞了好久 现在弄懂了
给出样例
废话不多说 乱枚举肯定超时 作如下处理
设
D + E - A = d1
C + E - A = -d1 + d2
C + A - B = -d2 + d3
B + D - B = -d3 + d4
A + B - E = -d4 + d5
将上述表达式消元 得到下列式子(di 等于 1 (进位) 或 0 (不进位)
A = x1 * d1 + x2 * d2 + x3 * d3 + x4 * d4 + x5 * d5
B = ...
C = ...
D = ...
E = ...
可以发现x的取值与d毫无关系 所以我们只要枚举d代入上式算出各值检验时候符合要求即可 (代码中x用g数组储存 d用above储存)
给出样例
5 ABCED BDACE EBBAA
废话不多说 乱枚举肯定超时 作如下处理
设
D + E - A = d1
C + E - A = -d1 + d2
C + A - B = -d2 + d3
B + D - B = -d3 + d4
A + B - E = -d4 + d5
将上述表达式消元 得到下列式子(di 等于 1 (进位) 或 0 (不进位)
A = x1 * d1 + x2 * d2 + x3 * d3 + x4 * d4 + x5 * d5
B = ...
C = ...
D = ...
E = ...
可以发现x的取值与d毫无关系 所以我们只要枚举d代入上式算出各值检验时候符合要求即可 (代码中x用g数组储存 d用above储存)
#include<cstdio> #include<algorithm> #include<iostream> #include<cmath> #include<cstring> using namespace std; #define MAXN 30 #define MAXM 64 typedef long long LL; int T[MAXM+10][MAXN+10], g[MAXN+10][MAXN+10]; int Last[MAXN+10], litole[MAXN+10], letoli[MAXN+10]; int n, above[MAXN+10]; int Ans[MAXM+10]; char s[3][MAXN+10]; int gcd(int a, int b) { while(b) { int r = a % b; a = b; b = r; } return a; } template <int maxn, int maxm> struct Maxtrix{ int equ, var; int A[maxn+10][maxm+10]; void init() { memset(A, 0, sizeof(A)); equ = var = 0; } void get_op(int i) { for(int j = 1; j <= var; j++) { // '<=' ? !!! A[i][j] = -A[i][j]; g[i][j] = -g[i][j]; } } void Gauss() { // 这里需要修改!!!!!! for(int row = 1; row <= equ; row++) { int Max = 0, f, col, k; for(col = 1; col <= var; col++) if(fabs(A[row][col]) > Max) { Max = fabs(A[row][col]); k = col; } if(!Max) continue; col = k; litole[row] = col; letoli[col] = row; if(A[row][col] < 0) get_op(row); for(int i = 1; i <= equ; i++) { if(i == row) continue; if(A[i][col] < 0) get_op(i); f = gcd(A[row][col], A[i][col]); for(int j = 1; j <= var; j++) { g[i][j] = g[i][j] * (A[row][col] / f) - g[row][j] * (A[i][col] / f); if(j == col) continue; A[i][j] = A[i][j] * (A[row][col] / f) - A[row][j] * (A[i][col] / f); } A[i][col] = 0; f = A[i][1]; for(int j = 2; j <= var; j++) { f = gcd(f, fabs(A[i][j])); f = gcd(f, fabs(g[i][j])); } if(!f || f == 1) continue; for(int j = 1; j <= var; j++) { A[i][j] /= f; g[i][j] /= f; } } } } }; Maxtrix <MAXM, MAXN> A; bool Check() { bool vis[MAXN+10]; memset(vis, 0, sizeof(vis)); for(int i = 1; i <= A.equ; i++) { int sum = 0; for(int j = 2; j <= n; j++) sum += above[j] * g[i][j]; if(sum % A.A[i][litole[i]] != 0) return false; sum /= A.A[i][litole[i]]; if(sum > n || sum < 0) return false; if(vis[sum]) return false; vis[Ans[i] = sum] = true; } return true; } void DFS(int cur) { if(cur > n) { if(!Check()) return ; printf("%d", Ans[letoli[1]]); for(int i = 2; i <= n; i++) printf(" %d", Ans[letoli[i]]); exit(0); } above[cur] = 0; DFS(cur+1); above[cur] = 1; DFS(cur+1); } int main() { scanf("%d", &n); for(int i = 0; i < 3; i++) scanf("%s", s[i]); A.init(); A.equ = A.var = n; for(int i=n-1;i>=0;i--) { T[i+1][s[0][i]-'A'+1]++; T[i+1][s[1][i]-'A'+1]++; T[i+1][s[2][i]-'A'+1]--; g[i+1][i+1]=n; g[i+1][i+2]=-1; } memcpy(A.A, T, sizeof(T)); A.Gauss(); DFS(2); }
相关文章推荐
- 【高斯消元】[NOIP2004]虫食算 —— 正解
- 【高斯消元】[NOIP2004]虫食算(这是正解)
- [NOIP2004][CODEVS1064]虫食算(搜索||高斯消元)
- [NOIP2004]虫食算 - 高斯消元|搜索
- noip2004 虫食算 (深搜,倒序枚举+高斯消元解方程组)
- bzoj 2337 [HNOI2011]XOR和路径【高斯消元+dp】
- 【BZOJ1013】球形空间产生器(高斯消元)
- CS Academy Round 52 An Unstable Graph 高斯消元+概率dp
- hiho一下第56周 高斯消元
- noip2004初赛-三角形内切圆的面积
- 高斯消元模版2—01方程组
- noip2004 花生采摘 (枚举)
- 用高斯消元解决一部分期望问题 学习笔记
- 【NOIP2004】【CJOJ1703】【洛谷1092】虫食算
- hdu5955Guessing the Dice Roll AC自动机+高斯消元
- HDU.3571.N-dimensional Sphere(高斯消元 模线性方程组)
- poj1222 高斯消元
- 1013: [JSOI2008]球形空间产生器sphere(高斯消元)
- HDU 4418 Time travel(高斯消元+概率DP)
- 高斯消元裸题 记录模板 BZOJ 1013