SRM 590 DIV1

来源:互联网 发布:单片机驱动12864 编辑:程序博客网 时间:2024/06/05 14:53

转载请注明出处,谢谢http://blog.csdn.net/ACM_cxlove?viewmode=contents    by---cxlove

水水更健康,终于回到1800+了。。。

DIV2 1000pt

显然每一列是独立的,分开考虑。

对于某一列,如果按单个字符U , D从下往上考虑的话,发现连续两个U的话,下面的U可以移动的位置受上面一个影响。

不过因此可以想到相邻的U , D互相限制位置,可以依次处理,相邻相同字符的话, 可以作为一个字符。

做法:把相邻的U合并,相邻的D合并,dp[i][j]表示前i个部分处理完,第i个部分最靠上的一个位置为j。

这样的话,如果当前为U,那么向上移动的最远位置为下一个部分最靠下的D的位置。

如果当前为D,那么向下移动的最远位置便是上一个部分最靠上的U的位置。

这样就可以搞出每一个部分的上下界,然后分别DP。

typedef long long LL;const LL MOD = 1000000007;const int N = 55;LL dp[N][N];void add (LL &a , LL b) {a += b;a = (a % MOD + MOD) % MOD;}LL mut (LL a , LL b) {a = a * b % MOD;a = (a + MOD) % MOD;return a;}LL gao_up (vector<int>&v , int limit) {int n = v.size();LL c[N][N]; memset (c , 0 , sizeof(c));c[n - 1][limit - 1] = 1;for (int i = n - 2 ; i >= 0 ; i --) {for (int j = limit ; j >= 0 ; j --) {if (c[i + 1][j] == 0) continue;for (int k = v[i] ; k < j ; k ++) {add (c[i][k] , c[i + 1][j]);}}}LL ans = 0;for (int i = 1 ; i <= limit ; i ++) {add (ans , c[0][i]);}return ans;}LL gao_down (vector<int>&v , int down , int up) {int n = v.size();LL c[N][N]; memset (c , 0 , sizeof(c));c[0][down] = 1;for (int i = 0 ; i < n ; i ++) {for (int j = 0 ; j <= up ; j ++) {if (c[i][j] == 0) continue;for (int k = j + 1 ; k <= v[i] ; k ++)add (c[i + 1][k] , c[i][j]);}}return c[n][up];}vector<vector<int> > v;class FoxAndShogi {public:int differentOutcomes(vector <string> board) {    int row = board.size() , col = board[0].size();    LL ans = 1LL;    for (int c = 0 ; c < col ; c ++) {    memset (dp , 0 , sizeof(dp));    string s = "";    v.clear ();    for (int r = row - 1 ; r >= 0 ; r --)    s = s + board[r][c];    int first = -1;    for (int i = 0 , pre = -1 ; i < s.size() ; i ++) {    if (s[i] == '.') continue;    if (s[i] == 'D' && pre == 0) {    v[v.size() - 1].push_back (i + 1);    }    else if (s[i] == 'U' && pre == 1) {    v[v.size() - 1].push_back (i + 1);    }    else {    if (first == -1) {    if (s[i] == 'U') first = 0;    else first = 1;    }    vector<int>t;    t.push_back(i + 1);    v.push_back(t);    if ( s[i] == 'U') pre = 1;    else pre = 0;    }    }    dp[0][0] = 1;    for (int i = 0 ; i < v.size() ; i ++) {    for (int j = 0 ; j <= row ; j ++) {    if (dp[i][j] == 0) continue;     // up    if ((first == 0 && i % 2 == 0) || (first == 1 && i % 2 == 1)){    int now = v[i][v[i].size() - 1];    int limit = (i + 1) < v.size() ? v[i + 1][0] : (col + 1);    for (int k = now ; k < limit ; k ++) {    add (dp[i + 1][k] , mut (dp[i][j] , gao_up (v[i] , k + 1)));    }    }    //down    else {    int now = v[i][v[i].size() - 1];    for (int k = j + 1 ; k <= now ; k ++) {    add (dp[i + 1][k] , mut (dp[i][j] , gao_down (v[i] , j , k)));    }    }    }    }    LL tmp = 0;    for (int i = 0 ; i <= row ; i ++)    add (tmp , dp[v.size()][i]);    // cout << tmp << endl;    ans = mut (ans , tmp);    }    return ans;}};

DIV1 250PT

把L,R全部提取出来,先判断下是否一致。

然后 比较下位置


DIV1 500 PT

异或结果 小于等于LIMIT,先处理相等的情况,既异或结果每一位都和LIMIT相等,列方程组,求一下秩。

否则的话,必然存在某一位,LIMIT中为1,实际为0,而且高位和LIMIT一致,低位任意 。

所以枚举相隔的这个位置,同样是列方程组求解。

typedef long long LL;int a[100][100];int n , m ;long long gauss(){    int i,j,row=1,col;    for (col=1;col<=m;++col){            for (i=row;i<=n;++i)            if (a[i][col])                break ;        if (i>n)            continue ;         if (i!=row){                for (j=col;j<=m;++j)                swap(a[row][j],a[i][j]);            swap(a[i][m + 1],a[row][m + 1]);        }        for (i=row+1;i<=n;++i)            if (a[i][col]){                    for (j=col;j<=m;++j)                    a[i][j]^=a[row][j];                a[i][m + 1]^=a[row][m + 1];            }        ++row;     }    for (i=row;i<=n;++i)        if (a[i][m + 1])            return 0;    return 1ll<<(long long)(m-row+1); }class XorCards {public:long long numberOfWays(vector<long long> number, long long limit) {    LL ans = 0;    m = number.size();n = 61;    memset (a , 0 , sizeof(a));    for (int i = 0 ; i < 61 ; i ++) {    for (int j = 0 ; j < m ; j ++) {    if (number[j] & (1LL << i)) a[i + 1][j + 1] = 1;    }    a[i + 1][m + 1] = (limit & (1LL << i)) ? 1 : 0;    }    ans = gauss ();    for (int i = 0 ; i < 61 ; i ++) {    if (!(limit & (1LL << i))) continue;    memset (a , 0 , sizeof(a));    for (int j = i + 1 ; j < 61 ; j ++) {    for (int k = 0 ; k < m ; k ++) {    if (number[k] & (1LL << j)) a[j + 1][k + 1] = 1;    }    a[j + 1][m + 1] = (limit & (1LL << j)) ? 1 : 0;    }     for (int k = 0 ; k < m ; k ++) {    if (number[k] & (1LL << i)) a[i + 1][k + 1] = 1;    }    ans += gauss ();    }    return ans;}};

DIV1 1000PT

按边的代价排序,然后 每次暴力迭代加边,folyd最短路后求价值。。。