zoukankan      html  css  js  c++  java
  • BZOJ3782 上学路线 【dp + Lucas + CRT】

    题目链接

    BZOJ3782

    题解

    我们把终点也加入障碍点中,将点排序,令(f[i])表示从((0,0))出发,不经过其它障碍,直接到达((x_i,y_i))的方案数
    首先我们有个大致的方案数({x_i + y_i choose x_i})
    但是中途可能会经过一些其它障碍点,那么就减去
    所以

    [f[i] = {x_i + y_i choose x_i} - sumlimits_{j = 1}^{i - 1} {x_i - x_j + y_i - y_j choose x_i - x_j}f[j] ]

    由于坐标很大,又观察到一种模数不大,一种模数为合数,且最大质因子也不大
    所以可以(Lucas)定理 + CRT合并

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<cmath>
    #include<map>
    #define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
    #define REP(i,n) for (int i = 1; i <= (n); i++)
    #define mp(a,b) make_pair<int,int>(a,b)
    #define cls(s) memset(s,0,sizeof(s))
    #define cp pair<int,int>
    #define LL long long int
    using namespace std;
    const int maxn = 205,maxm = 1000005,INF = 1000000000;
    inline LL read(){
    	LL out = 0,flag = 1; char c = getchar();
    	while (c < 48 || c > 57){if (c == '-') flag = -1; c = getchar();}
    	while (c >= 48 && c <= 57){out = (out << 3) + (out << 1) + c - 48; c = getchar();}
    	return out * flag;
    }
    LL N,M,T,P;
    struct point{LL x,y;}p[maxn];
    inline bool operator <(const point& a,const point& b){
    	return a.x == b.x ? a.y < b.y : a.x < b.x;
    }
    int pr[10],pi;
    LL fac[5][maxm],fv[5][maxm],inv[5][maxm];
    void sp(){
    	int x = P;
    	for (int i = 2; i * i <= x; i++)
    		if (x % i == 0){
    			pr[++pi] = i;
    			x /= i;
    		}
    	if (x - 1) pr[++pi] = x;
    }
    void init(){
    	for (int j = 1; j <= pi; j++){
    		fac[j][0] = fac[j][1] = fv[j][0] = fv[j][1] = inv[j][0] = inv[j][1] = 1;
    		int p = pr[j];
    		for (int i = 2; i < pr[j]; i++){
    			fac[j][i] = 1ll * fac[j][i - 1] * i % p;
    			inv[j][i] = 1ll * (p - p / i) * inv[j][p % i] % p;
    			fv[j][i] = 1ll * fv[j][i - 1] * inv[j][i] % p;
    		}
    	}
    }
    LL Lucas(LL n,LL m,int p){
    	if (m > n) return 0;
    	if (n < pr[p] && m < pr[p])
    		return 1ll * fac[p][n] * fv[p][m] % pr[p] * fv[p][n - m] % pr[p];
    	return 1ll * Lucas(n % pr[p],m % pr[p],p) * Lucas(n / pr[p],m / pr[p],p) % pr[p];
    }
    LL C(LL n,LL m){
    	if (m > n) return 0;
    	LL re = 0;
    	for (int i = 1; i <= pi; i++){
    		re = (re + 1ll * Lucas(n,m,i) * (P / pr[i]) % P * inv[i][P / pr[i] % pr[i]] % P) % P;
    	}
    	return re;
    }
    LL f[maxn];
    int main(){
    	N = read(); M = read(); T = read(); P = read();
    	sp(); init();  //REP(i,pi) printf("%d ",pr[i]); puts("");
    	REP(i,T) p[i].x = read(),p[i].y = read();
    	++T;
    	p[T].x = N,p[T].y = M;
    	sort(p + 1,p + T + 1);
    	for (int i = 1; i <= T; i++){
    		f[i] = C(p[i].x + p[i].y,p[i].x);
    		for (int j = 1; j < i; j++)
    			if (p[j].x <= p[i].x && p[j].y <= p[i].y)
    				f[i] = (f[i] - 1ll * f[j] * C(p[i].x - p[j].x + p[i].y - p[j].y,p[i].x - p[j].x) % P) % P;
    		f[i] = (f[i] + P) % P;
    		if (p[i].x == N && p[i].y == M){
    			printf("%lld
    ",f[i]);
    		}
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    分层图最短路(DP思想) BZOJ2662 [BeiJing wc2012]冻结
    动态规划 BZOJ1925 地精部落
    线性DP SPOJ Mobile Service
    线性DP codevs2185 最长公共上升子序列
    数位DP POJ3208 Apocalypse Someday
    线性DP POJ3666 Making the Grade
    杨氏矩阵 线性DP? POJ2279 Mr.Young's Picture Permutations
    tarjan强连通分量 洛谷P1262 间谍网络
    树链剖分 BZOJ3589 动态树
    二分图 BZOJ4554 [Tjoi2016&Heoi2016]游戏
  • 原文地址:https://www.cnblogs.com/Mychael/p/9190939.html
Copyright © 2011-2022 走看看