zoukankan      html  css  js  c++  java
  • BZOJ 3782: 上学路 Lucas+ExCRT+容斥+dp

    其实呢,扩展中国剩余定理还有一种理解方式:就是你有一坨东西,形如:
    $A[i]equiv B[i](mod$ $P[i])$.
    对于这个东西,你可以这么思考:
    如果最后能求出一个解,那么这个解的增量一定是 $lcm(P[1],P[2].....).$
    所以,只要你能找到一坨 $P[i]$,使得它们的 $lcm$ 等于你想要的东西,你就可以用 $excrt$来解.

    p话扯完了,我们步入正题:
    假设没有障碍,有 $n$ 行 $m$ 列,那么答案即为 $C_{n+m}^{n}.$
    这个东西就代表你一共会走 $n+m$ 步,其中 $n$ 步的方向是向上的.
    而如果有障碍,我们考虑按照每一个障碍点一次枚举.
    首先,将障碍按照横纵坐标从小到大拍一个序,那么考虑我们枚举到第 $i$ 个障碍.
    令 $f[i]$ 表示从起点到第 $i$ 个障碍所走过的合法的方案数,$(x,y)$ 表示横纵坐标.
    总方案为 $C_{x+y}^{y},$ 不合法的方案为 $sum f[前面障碍]$.
    如果随便减的话,我们可能减多,所以我们考虑按照策略去减.
    我们想让每一次减掉的都互不相同,所以我们考虑枚举第一个不合法的障碍.
    即 $C_{x+y}^{y}-sum_{j=1}^{i-1}f[j] imes calc(j到i的方案数).$
    这样,我们等于说是强制性的每次只减掉第一个障碍碰到 $j$ 的方案数,不会减多.
    这个题的模数不是素数,所以需要将模数分解成若干个素数,然后依次取模,最后在用 $excrt$ 合并.

    Code:

    #include <cstdio> 
    #include <algorithm>  
    #define N 1000006    
    #define ll long long   
    #define setIO(s) freopen(s".in","r",stdin) 
    using namespace std;    
    ll F[N];       
    int array[10]={0,3,5,6793,10007};
    struct Node {
    	ll x,y;  
    	Node(ll x=0,ll y=0):x(x),y(y){} 
    }arr[N];     
    bool cmp(Node a,Node b) {
    	return a.x==b.x?a.y<b.y:a.x<b.x; 
    }        
    ll qpow(ll base,ll k,ll mod) {
    	ll tmp=1; 
    	for(;k;k>>=1,base=base*base%mod) 
    		if(k&1) tmp=tmp*base%mod; 
    	return tmp;       
    }
    struct Lucas { 
    	int mod; 
    	int fac[N];     
    	int inv(int i) { 
    		return (int)qpow(i,mod-2,mod); 
    	}
    	void init(int p) {  
    		mod=p,fac[0]=1;   
    		for(int i=1;i<=mod;++i) fac[i]=(ll)fac[i-1]*i%mod;    
    	} 
        int C(int x,int y) { 
        	if(y>x) return 0; 
        	if(y==0) return 1;    
        	return (int)(1ll*fac[x]*inv(fac[y])%mod*inv(fac[x-y])%mod);      
        }     
        int solve(ll x,ll y) {
        	if(y>x) return 0; 
        	if(y==0) return 1;     
        	return (int)(1ll*solve(x/mod,y/mod)*C(x%mod,y%mod)%mod);   
        }
    }comb[8];  
    struct excrt { 
    	ll arr[N],brr[N];   
    	ll exgcd(ll a,ll b,ll &x,ll &y) {
    		if(!b) { 
    			x=1,y=0; 
    			return a; 
    		} 
    		ll gcd=exgcd(b,a%b,x,y),tmp=x;       
    		x=y,y=tmp-a/b*y;      
    		return gcd;      
    	}    
    	ll Excrt() { 
    		int i,j; 
    		ll ans=arr[1],M=brr[1];        
            for(i=2;i<=4;++i) {
            	ll a=M,b=brr[i],c=arr[i]-ans,gcd,x,y;
            	gcd=exgcd(a,b,x,y),b=abs(b/gcd);            
            	x=(x*(c/gcd)%b+b)%b;           
            	ans+=M*x;   
            	M*=brr[i]/__gcd(brr[i],M);    
            	ans=(ans%M+M)%M; 
            } 
            return ans;    
    	}
    }crt;            
    ll C(ll a,ll b,int ty) {   
    	if(ty==0) 
    		return comb[0].solve(a,b);   
    	else {
    		int i,j; 
    		for(i=1;i<=4;++i) {                         
    			crt.arr[i]=comb[i].solve(a,b); 
    			crt.brr[i]=array[i];                     
    		}
    	} 
    	return crt.Excrt();  
    }
    int main() {
    	int i,j,k,flag;   
    	// setIO("input"); 
    	ll n,m,mod;   
    	scanf("%lld%lld%d%lld",&n,&m,&k,&mod),flag=(mod==1019663265);   
    	if(!flag) {
    		comb[0].init(mod);   
    	}
    	else { 
    		for(i=1;i<=4;++i) 
    			comb[i].init(array[i]); 
    	}              
    	for(i=1;i<=k;++i) 
    		scanf("%lld%lld",&arr[i].x,&arr[i].y);           
    	arr[++k].x=n,arr[k].y=m;    
    	sort(arr+1,arr+1+k,cmp);                                                          
    	for(i=1;i<=k;++i) { 
    		F[i]=C(arr[i].x+arr[i].y,arr[i].y,flag); 
    		for(j=1;j<i;++j) {
    			if(arr[j].y<=arr[i].y) 
    				F[i]=(F[i]-(F[j]*C(arr[i].x-arr[j].x+arr[i].y-arr[j].y,arr[i].y-arr[j].y,flag)%mod)+mod)%mod;     
    		}
    	} 
    	printf("%lld
    ",F[k]);   
    	return 0;      
    }
    

      

  • 相关阅读:
    CSU 1333 Funny Car Racing
    FZU 2195 检查站点
    FZU 2193 So Hard
    ZOJ 1655 FZU 1125 Transport Goods
    zoj 2750 Idiomatic Phrases Game
    hdu 1874 畅通工程续
    hdu 2489 Minimal Ratio Tree
    hdu 3398 String
    洛谷 P2158 [SDOI2008]仪仗队 解题报告
    POJ 1958 Strange Towers of Hanoi 解题报告
  • 原文地址:https://www.cnblogs.com/guangheli/p/11514720.html
Copyright © 2011-2022 走看看