• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            Why so serious? --[NKU]schindlerlee

            2010年02月17日星期三.sgu197 矩陣快乘 + 高精除法 + 狀態dp

            2010年02月17日星期三.sgu197 矩陣快乘 + 高精除法 + 狀態dp
            sgu197:矩陣快乘 + 高精除法 + dp
            題目中的m范圍如此之小,一看就有問題,很容易想到狀態壓縮。
            兩行之間的不同狀態表示,可以用矩陣表示兩行的狀態轉移。

            矩陣中的元素為1,表示兩行狀態可達,元素為0 ,表示狀態非法,也就是兩行狀態不可達。

                       stat[0][0] stat[0][1] stat[0][2] stat[0][3]
            stat[1][0]      0          1          1          1          
            stat[1][1]      1          1          1          1          
            stat[1][2]      1          1          1          1          
            stat[1][3]      1          1          1          0          

            如果再在矩陣的右側乘以一個列向量,每個元素是能到達這個元素所表示狀態的染色方法種數,
            那么乘得的一個列向量所表示的就是新的能到達新的一行的各種狀態的種數。

            很容易想到,對于題目中所提到的n,和轉移矩陣M,
            所求的結果也就是 M^(n-1) 再乘以一個全一的初始狀態列向量,再求出所有元素的和即可。

            而對于題目中提到的巨大的n,可以使用二分矩陣乘法來處理。
            所以最后的復雜度也就是 ,矩陣乘法的復雜度*二分的復雜度。
            最大的計算量 = 32 * 32 * 32 * log(10^100)  = 3276800,兩秒的時間,夠了。
              1 
              2 const int M = 32;
              3 #define bin(x) (1 <<(x))
              4 int n,m,mod,mask;
              5 struct Matrix {
              6     int m[M][M];
              7     Matrix(){memset(m,0,sizeof(m));}
              8     Matrix operator = (Matrix b) {
              9         for (int i = 0;i <= mask;i++) {
             10             for (int j = 0;j <= mask;j++) {
             11                 m[i][j] = b.m[i][j];
             12             }
             13         }
             14         return *this;
             15     }
             16 }org,bas,res;
             17 Matrix mul(Matrix a,Matrix b)
             18 {
             19   Matrix c;
             20   for (int i = 0;i <= mask;i++) {
             21       for (int j = 0;j <= mask;j++) {
             22           for (int k = 0;k <= mask;k++) {
             23               c.m[i][j] = (c.m[i][j] + a.m[i][k] * b.m[k][j]) % mod;
             24           }
             25       }
             26   }
             27   return c;
             28 }
             29 
             30 char s[512];
             31 int d[512],len;
             32 int two[2048],top;
             33 
             34 void div() {
             35     int i,j,k,left = 0;
             36     for (i = len - 1;i >= 0;i--,left *= 10) {
             37         int tmp = d[i] + left;
             38         if (tmp < 2) {
             39             left = d[i];
             40             d[i] = 0;
             41         }else {
             42             d[i] = tmp / 2;
             43             left = tmp % 2;
             44         }
             45     }
             46     while (d[len - 1== 0 && len > 0) { len--; }
             47 }
             48 
             49 void pre()
             50 {
             51   int i,j,k;
             52   len = strlen(s);
             53   for (i = 0;i < len;i++) { d[len - 1 - i] = s[i] - '0'; }
             54   while (len > 0) {
             55       two[top++= d[0% 2;
             56       div();
             57   }
             58   mask = bin(m) - 1;
             59   for (i = 0;i <= mask;i++) {
             60       for (j = 0;j <= mask;j++) {
             61           int tmp = i&j;
             62           if ((tmp&3== 3 || (tmp&6== 6 ||
             63               (tmp&12== 12 || (tmp&24== 24) { continue; }
             64           tmp = (~& ~j) & mask;
             65           if ((tmp&3== 3 || (tmp&6== 6 ||
             66               (tmp&12== 12 || (tmp&24== 24) { continue; }
             67           org.m[i][j] = 1;
             68       }
             69   }
             70 }
             71 //http://www.shnenglu.com/schindlerlee
             72 int main()
             73 {
             74   int i,j,k;
             75   scanf("%s %d %d",s,&m,&mod);
             76   pre();
             77   if (len == 1 && s[0== '1') {
             78       printf("%d\n",bin(m));
             79       return 0;
             80   }
             81   for (i = 0;two[i] == 0;i++);
             82   for (two[i] = 0,j = 0;j < i;j++ ) {
             83       two[j] = 1;
             84   }
             85   while (two[top-1== 0) { top--; }
             86 
             87   bas = org;
             88   for (i = 0;i <= mask;i++) { res.m[i][i] = 1; }
             89   for (i = 0;i < top;i++) {
             90       if (two[i]) {
             91           res = mul(res,bas);
             92       }
             93       bas = mul(bas,bas);
             94   }
             95   int ans = 0;
             96   for (i = 0;i <= mask;i++) {
             97       for (j = 0;j <= mask;j++) {
             98           ans = (ans + res.m[i][j]) % mod;
             99       }
            100   }
            101   printf("%d\n",ans);
            102   return 0;
            103 }
            104 
            105 


            posted on 2010-02-17 01:29 schindlerlee 閱讀(1476) 評論(0)  編輯 收藏 引用

            91久久婷婷国产综合精品青草| 99久久精品免费看国产一区二区三区 | 99国产欧美精品久久久蜜芽| 狠狠色婷婷久久一区二区三区| 精品免费久久久久久久| 国产精品青草久久久久福利99| 久久久精品人妻无码专区不卡| 无遮挡粉嫩小泬久久久久久久 | 亚洲精品国产第一综合99久久| 久久www免费人成看片| 国产精品美女久久久久AV福利| 狠狠色丁香久久婷婷综合_中 | 亚洲人成网站999久久久综合| 久久精品国产亚洲AV影院| 国产精品久久久久一区二区三区 | 久久久久久久综合综合狠狠| 无码国内精品久久人妻| 日韩影院久久| 中文字幕久久欲求不满| 久久棈精品久久久久久噜噜| 人妻无码久久精品| 狠狠久久综合| 国产精品99久久久久久www| 久久久亚洲欧洲日产国码aⅴ | 亚洲中文字幕无码一久久区| 色综合久久中文字幕综合网| 国产成人久久精品二区三区| 久久精品国产精品亚洲精品| 婷婷伊人久久大香线蕉AV| 伊人 久久 精品| 久久强奷乱码老熟女网站| 久久99热这里只有精品国产| 久久午夜福利无码1000合集| 久久综合九色综合久99| 国产午夜精品久久久久九九| 91久久精品国产免费直播| 久久免费视频网站| 久久精品国产亚洲一区二区三区 | 亚洲午夜精品久久久久久浪潮 | 色综合久久88色综合天天 | 亚洲美日韩Av中文字幕无码久久久妻妇|