Posts Tagged 二分
HDOJ 2429 Word Game
成都网络赛的题目,这题可以用矩阵乘法求解。以单词为点,能前后相连的单词之间连边,得到一个有向图,求长度为奇数且小于等于N的不同的S->T的路径数。设该有向图的邻接矩阵为A,则可通过求A + A ^ 3 + … + A ^ N求解。
因为 N 比较大所以要通过二分来求矩阵和,即 A + A ^ 3 + A ^ 5 + A ^ 7 = (A + A ^ 3) + A^4 * (A + A ^ 3)。贴下代码:
- #include <iostream>
- #include <cstring>
- using namespace std;
- char tem[33][12];
- int l[33], t, m, n;
- class matrix{
- public :
- int rw;
- int cn;
- int ma[33][33];
- matrix()
- {
- rw = 0;
- cn = 0;
- }
- matrix(int &x, int &y)
- {
- int i, j;
- rw = x;
- cn = y;
- for(i = 0; i < rw; i++)
- for(j = 0; j < cn; j++)
- ma[i][j] = 0;
- }
- matrix(const matrix &x)
- {
- int i, j;
- rw = x.rw;
- cn = x.cn;
- for(i = 0; i < rw; i++)
- for(j = 0; j < cn; j++)
- ma[i][j] = x.ma[i][j];
- }
- matrix operator*(matrix &x)
- {
- int i, j, k;
- matrix ret(cn, x.rw);
- for(i = 0; i < rw ; i++)
- for(j = 0; j < x.cn ; j++)
- {
- for(k = 0; k < cn; k++)
- ret.ma[i][j] += ma[i][k] * x.ma[k][j];
- if(ret.ma[i][j] > 10001)
- ret.ma[i][j] %= 10001;
- }
- return ret;
- }
- matrix power(int x)
- {
- matrix ret(rw, cn);
- if(x == 1)
- return *this;
- if(x == 2)
- {
- int i, j ,k;
- for(i = 0; i < rw; i++)
- for(j = 0; j < cn; j++)
- {
- for(k = 0; k < cn; k++)
- ret.ma[i][j] += ma[i][k] * ma[k][j];
- if(ret.ma[i][j] >= 10001)
- ret.ma[i][j] %= 10001;
- }
- }
- else if((x & 1) == 0)
- {
- ret = this->power(x >> 1);
- ret = ret.power(2);
- }
- else
- {
- ret = this->power(x >> 1);
- ret = ret.power(2);
- ret = ret * (*this);
- }
- return ret;
- }
- inline matrix operator+= (const matrix &x)
- {
- int i, j;
- for(i = 0; i < rw; i++)
- for(j = 0; j < cn; j++)
- {
- ma[i][j] += x.ma[i][j];
- if(ma[i][j] > 10001)
- ma[i][j] %= 10001;
- }
- return *this;
- }
- inline matrix operator = (const matrix &x)
- {
- int i, j;
- rw = x.rw;
- cn = x.cn;
- for(i = 0; i < rw; i++)
- for(j = 0; j < cn; j++)
- ma[i][j] = x.ma[i][j];
- return *this;
- }
- };
- inline matrix mtx(matrix <r, int n)
- {
- if((n & 1) == 0) n--;
- if(n == 1) return ltr;
- int tmp = (n + 1) >> 1;
- matrix ret, t1, t2;
- t1 = mtx(ltr, tmp - 1);
- t2 = ltr.power(tmp);
- if((tmp & 1) == 0)
- {
- ret = t2;
- ret = ret * t1;
- ret += t1;
- }
- else
- {
- ret = t2 * ltr;
- ret = ret * t1;
- ret += t1;
- ret += t2;
- }
- return ret;
- }
- int main()
- {
- int i, j;
- int st, ed;
- matrix ret;
- scanf("%d", &t);
- while(t--)
- {
- scanf("%d", &m);
- for(i = 0; i < m + 2; i++)
- {
- scanf("%s", tem[i]);
- l[i] = strlen(tem[i]);
- }
- scanf("%d", &n);
- matrix ltr(m, m);
- st = -1; ed = -1;
- for(i = 0; i < m; i++)
- {
- if(st == -1 && strcmp(tem[i], tem[m]) ==0)
- st = i;
- if(ed == -1 && strcmp(tem[i],tem[m+1])==0)
- ed = i;
- for(j= 0; j < m; j++)
- {
- if(tem[i][l[i]-1] == tem[j][0])
- ltr.ma[i][j] = 1;
- }
- }
- ret = mtx(ltr, n);
- printf("%dn", ret.ma[st][ed]);
- }
- return 0;
- }









