zoukankan      html  css  js  c++  java
  • P4478 [BJWC2018]上学路线

    n 和 m 都很大,所以可以从 T 的角度考虑,根据障碍点进行 dp。

    然后设 f[i]表示表示第一次经过 i 且 i 为第一个障碍时的方案数。

    然后考虑容斥,有:

    [f[i]=C_{p[i].x+p[i].y}^{p[i].x}-sum_{j}[p[j].x<=p[i].x& & p[j].y<=p[i].y]f[j] imes C_{p[i].x-p[j].x+p[i].y-p[j].y}^{p[i].x-p[j].x} ]

    然后排序一下,

    然后由于 n,m 很大,所以可以用 Lucas 定理求组合数,然后由于模数可能不是质数,所以还要用 CRT 合并。

    复杂度:(O(T^2log_{mod}N))

    code:

    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    const int N=207;
    const int M=1000007;
    template <class I>
    inline void read(I &x){
        int f=1;
        char c;
        for(c=getchar();c<'0'||c>'9';c=getchar()) if(c=='-') f=-1;
        for(x=0;c>='0'&&c<='9';x=(x<<3)+(x<<1)+(c&15),c=getchar());
        x*=f;
    }
    ll n,m,T,P,jc[M],invjc[M],f[N],ans;
    struct node{
    	ll x,y;
    	inline bool operator < (const node &a) const{
    		return x==a.x?y<a.y:x<a.x;
    	}
    	inline void rd(){
    		read(x),read(y);
    	}
    }p[N];
    ll ksm(ll x,ll y,ll mod){
    	ll res=1;
    	while(y){
    		if(y&1) res=1ll*res*x%mod;
    		x=1ll*x*x%mod;
    		y>>=1;
    	}
    	return res;
    }
    ll exgcd(ll a,ll b,ll &x,ll &y){
    	if(b==0) {x=1,y=0;return a;}
    	ll d=exgcd(b,a%b,x,y);
    	ll z=x;x=y,y=z-(a/b)*y;
    	return d;
    }
    ll C(ll x,ll y,ll mod){
    	if(y>x) return 0;
    	if(x<mod&&y<mod) return 1ll*jc[x]*invjc[y]%mod*invjc[x-y]%mod;
    	return 1ll*C(x%mod,y%mod,mod)*C(x/mod,y/mod,mod)%mod;
    }
    ll solve(ll mod){
    	jc[0]=jc[1]=1;
    	for(ll i=2;i<mod;i++)
    		jc[i]=1ll*jc[i-1]*i%mod;
    	invjc[mod-1]=ksm(jc[mod-1],mod-2,mod);
    	for(ll i=mod-2;i>=0;i--)
    		invjc[i]=1ll*invjc[i+1]*(i+1)%mod;
    	for(ll i=1;i<=T+1;i++){
    		f[i]=C(p[i].x+p[i].y,p[i].x,mod);
    		for(ll j=1;j<i;j++)
    			if(p[j].x<=p[i].x&&p[j].y<=p[j].y)
    				f[i]=(((ll)f[i]-1ll*f[j]*C(p[i].x+p[i].y-p[j].x-p[j].y,p[i].x-p[j].x,mod))%mod+mod)%mod;
    	}
    	return f[T+1];
    }
    ll bing(ll a,ll b,ll c){
        ll x=0,y=0;
        exgcd(a,c,x,y);
        x=(x%c+c)%c;
        return 1ll*x*a%P*b%P;
    }
    int main(){
    	read(n),read(m),read(T),read(P);
    	for(ll i=1;i<=T;i++)
    		p[i].rd();
    	p[T+1].x=n,p[T+1].y=m;
    	sort(p+1,p+2+T);
    	if(P==1000003) {
    		printf("%lld
    ",solve(1000003));
    		return 0;
    	}
    	ll ans1=solve(3),ans2=solve(5),ans3=solve(6793),ans4=solve(10007);
    	ans=(ans+bing(P/3,ans1,3))%P;
    	ans=(ans+bing(P/5,ans2,5))%P;
    	ans=(ans+bing(P/6793,ans3,6793))%P;
    	ans=(ans+bing(P/10007,ans4,10007))%P;
    	cout<<ans<<endl;
    	return 0;
    }
    
    
  • 相关阅读:
    css笔记图
    C#基础(四)条件、循环和判断
    C#基础(三)引用类型和预定义值类型
    C#基础(二)变量和常量
    C#基础(一)
    jquery实现全选和取消全选
    jquery easyUI datagrid自动计算两列的值
    纯CSS竖直菜单
    easyui被activeX控件挡住的解决方法
    jquery实现WIN7本地磁盘容量条效果
  • 原文地址:https://www.cnblogs.com/Hikigaya/p/11743844.html
Copyright © 2011-2022 走看看