zoukankan      html  css  js  c++  java
  • BZOJ_4386

    今天下午BZ在维护,我就用同学拿到的数据(权限号好爽)跑过了,等会晚上再交吧。这道题一看就是矩阵快速幂,最开始没有想到拆点的做法只想到了拆边,复杂度直接爆掉了。所以我们把每个点拆成3个,分别表示长度为1,2,3的边该连到这个点的哪个分身(不想画图了以后自己忘了自己YY吧)。然后开始矩阵快速幂,里面可以顺便处理出长度为L时,0~L的总方案数。最开始想到的比较蠢的做法是二分。强加了一个LOG,肯定是过不了的(这道题有56个点),所以我们预处理出2的logk*3次幂的矩阵,然后像倍增一样倒着加进去。

     1 #include <cstdio>
     2 #include <iostream>
     3 #include <algorithm>
     4 #include <cstdlib>
     5 #include <cstring>
     6 #include <cmath>
     7 using namespace std;
     8 const int N = 43;
     9 const int M = 1003;
    10 const double LOG = log(3*1000000000000000000LL);
    11 struct rp {
    12     long long w[N*3][N*3];
    13 }need[64],ans;
    14 long long st[3*N];
    15 int n,m;
    16 unsigned long long k;
    17 bool flag = false;
    18 inline rp cheng(rp a,rp b) {
    19     rp c;
    20     flag = false;
    21     memset(c.w,0,sizeof(c.w));
    22     for(int i = 1 ; i <= n*3+1 ; ++i)
    23         for(int k = 1 ; k <= n*3+1 ; ++k)
    24             if(!a.w[i][k])
    25             for(int j = 1 ; j <= n*3+1 ; ++j) {
    26                 c.w[i][j] += a.w[i][k]*b.w[k][j];
    27                 if(c.w[i][j] < 0) {
    28                     flag = true;
    29                     return a;
    30                 }
    31             }
    32     return c;
    33 }
    34 int main() {
    35     scanf("%d%d",&n,&m);
    36     cin >> k;
    37     for(int i = 1 ; i <= m ; ++i) {
    38         int x,y,d;
    39         scanf("%d%d%d",&x,&y,&d);
    40         if(d==1) need[0].w[y][x]++,st[y]++;
    41         if(d==2) need[0].w[y+n][x]++,st[y+n]++;
    42         if(d==3) need[0].w[y+2*n][x]++,st[y+2*n]++;
    43     }
    44     for(int i = 1 ; i <= n ; ++i) need[0].w[i][i+n]++;
    45     for(int i = 1 ; i <= n ; ++i) need[0].w[i+n][i+2*n]++;
    46     for(int i = 1 ; i <= n ; ++i) need[0].w[3*n+1][i] = 1;
    47     for(int i = 1 ; i <= 3*n+1 ; ++i) ans.w[i][i] = 1;
    48     need[0].w[3*n+1][3*n+1] = 1;
    49     unsigned long long kk = 1;
    50     int cnt = 0;
    51     do {
    52         kk<<=1;
    53         if(kk>3*k) break;
    54         cnt++;
    55         need[cnt] = cheng(need[cnt-1],need[cnt-1]);
    56         if(flag) {
    57             cnt--;
    58             break;
    59         }
    60     }while(1);
    61     unsigned long long ans2 = 0;
    62     for(int i = cnt ; i >= 0 ; --i) {
    63         kk>>=1;
    64         rp linshi = cheng(ans,need[i]);
    65         if(flag) continue;
    66         unsigned long long linshi2 = 0;
    67         for(int i = 1 ; i <= 3*n+1 ; ++i) linshi2 += (linshi.w[3*n+1][i]*st[i]);
    68         if(linshi2 < k) {
    69             ans = linshi;
    70             ans2 ^= kk;
    71         }
    72     }
    73     if(ans2 > k*3) cout << -1;
    74     else cout << ans2 + 1;
    75 }
    View Code

    我跑得比唐宇豪慢啊慢啊。对了这道题开教会了我矩阵快速幂的常数优化,就是for i j k 的顺序换成for i k j然后判断第一个矩阵的i,k是不是为零,为零的话就直接continue掉。快了50倍呢。那个LOG不要管,是我判读爆没有的时候开始的乱搞。后来判断爆没有是看它是不是负数,还是比较靠谱。

  • 相关阅读:
    tornado源码分析-多进程
    create a cocos2d-x-3.0 project in Xcode
    记录自己的傻逼的错误:找不到或无法载入主类
    MVC5 Entity Framework学习之实现主要的CRUD功能
    Linux中实现多网卡绑定总结
    it码农之心灵鸡汤(一)
    【高级算法】遗传算法解决3SAT问题(C++实现)
    MySQL-分区表-1
    OpenSift源代码编译过程记录
    Android Studio 视图解析
  • 原文地址:https://www.cnblogs.com/registerzxr/p/5130130.html
Copyright © 2011-2022 走看看