codeforce#420 E. Okabe and El Psy Kongroo(图论+矩阵快速幂)

题目链接

E. Okabe and El Psy Kongroo

分析

首先对于坐标为 (x,y) 的点,设 f(x,y) 表示从原点到 (x,y) 的路径不难得到递推公式 f(x,y)=f(x1,y1)+f(x1,y)+f(x1,y+1) ,很明显这和把每个点建图然后能达点建边构造的图是一样的,显然计算复杂度太高,观察表达式,我们发现 x 并没有什么作用,因为只能向前走 ( x>x+1 ),因此我们可以只对 y 坐标建图,建立邻接矩阵,对于点 (i,j) 如果可以从 y=i>y=j 则设 d[i][j]=1 矩阵 dk[i][j]y=iky=j 那么只需对每一条线段都建立这样的矩阵,然后计算 dbiai 再把所有矩阵相乘就是答案.

AC code

#include
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define INF 0x3f3f3f3f
#define ALL(x) (x.begin(),x.end())
#define ms(x,v) memset(x,v,sizeof(x))
using namespace std;
typedef long long LL;

typedef pair Pair;

typedef pair<int,pair<int,int> > Point;

const int maxn = 3e5+10;
const LL MOD = 1e9+7;
const int sz = 16;
struct matrix{
   LL m[sz][sz];
   matrix(){
      ms(m,0);
   }
   void init(int y){
      ms(m,0);
      for(int i=1 ; i1]=m[i][i-1] = m[i][i] =1;
      }
      if(y)m[0][1]=m[0][0] = m[y][y]=m[y][y-1] =1;
      else m[0][0] =1;
   }
   void init(){
      for(int i=0 ; i1;
   }
   void print(){
      for(int i=0 ;ifor(int j=0 ; jstd::cout << m[i][j] << ' ';
         std::cout  << '\n';
      }
   }
};


matrix mul(matrix& A,matrix & B){
   matrix ret;
   for(int i=0 ; ifor(int j=0 ; j0;
         for(int k=0 ; kreturn ret;
}

matrix power_mod(matrix x,LL n){
   matrix ret;
   ret.init();
   while (n) {
      //std::cout << "n = " <
      if(n&1)ret = mul(ret,x);
      x = mul(x,x);
      //ret.print();
      n>>=1;
   }
   return ret;
}

matrix A[2];

int main(){

  ios::sync_with_stdio(false);
  cin.tie(0);

  LL n,k;
  cin>>n>>k;
  int t=0;
  ms(A,0);
  A[t].init();
  for(LL i=0  ; icin>>a>>b>>y;
     if(i == n-1)b=k;
     t ^=1;

     A[t].init(y);
     A[t] = power_mod(A[t],b-a);

     A[t] = mul(A[t^1],A[t]);

 }

   std::cout << A[t].m[0][0] << '\n';


  return 0;
  }

参考

editorial

你可能感兴趣的:(算法&数据结构)