• bzoj 3782 上学路线 卢卡斯定理 容斥 中国剩余定理 dp


    LINK:上学路线

    从(0,0)走到(n,m)每次只能向上或者向右走 有K个点不能走求方案数,对P取模.

    (1leq N,Mleq 10^10 0leq Tleq 200)

    p=1000003或p=1019663265

    考虑dp......(没啥意义.

    要求出 从(0,0)到(n,m)不经过一个障碍点的方案数 显然需要容斥. 所有方案C(n+m,n).

    还是考虑dp 将T个障碍点排序之后可以发现 后面的点一定不会经过前面的点。

    设f[i]表示到达第i个点且不经过前面i-1个点的方案数。我们把终点也当成障碍点 可以发现最后一个f值就是答案辣.

    这个是一个很经典的代表元容斥.

    考虑到达i这个点 的总方案数 C((x_i+y_i,x_i)).过程中肯定会经过其他的点的。

    我们只需要知道经过的第一个不合法的点是谁就可以减掉对应的不合法方案辣。

    可以发现这样做把所有的不合法方案都给减掉了。

    复杂度T^2. 考虑过程中的组合数怎么做 卢卡斯定理!

    P=10000003还好做一点 P=1019663265...

    经典套路 摁两下计算器就会了 1019663265=5×3×6793×10007.四个都是质数。

    比扩展卢卡斯要简单一点的东西 可以中国剩余定理来解决。

    const ll MAXN=1000010,maxn=210;
    ll n,m,k,mod,p,xx,yy;
    struct wy
    {
    	ll inv[MAXN];
    	ll fac[MAXN];
    	ll mod,ans;
    }t[5];
    ll f[maxn];
    struct jl{ll x,y;}s[maxn];
    inline ll ksm(ll b,ll p,ll mod)
    {
    	ll cnt=1;//cout<<b<<endl;
    	while(p)
    	{
    		if(p&1)cnt=cnt*b%mod;
    		b=b*b%mod;p=p>>1;
    	}
    	return cnt;
    }
    inline void prepare()
    {
    	rep(1,p,i)
    	{
    		ll maxx=m(i)-1;t[i].fac[0]=1;
    		rep(1,maxx,j)t[i].fac[j]=t[i].fac[j-1]*j%m(i);
    		t[i].inv[maxx]=ksm(t[i].fac[maxx],m(i)-2,m(i));
    		fep(maxx-1,0,j)t[i].inv[j]=t[i].inv[j+1]*(j+1)%m(i);
    	}
    }
    inline ll cmp(jl a,jl b){return a.x==b.x?a.y<b.y:a.x<b.x;}
    inline ll C(ll p,ll a,ll b){return t[p].fac[a]*t[p].inv[b]%m(p)*t[p].inv[a-b]%m(p);}
    inline ll Lucas(ll p,ll a,ll b)
    {
    	if(a<b)return 0;
    	if(a<m(p))return C(p,a,b);
    	return Lucas(p,a/m(p),b/m(p))*Lucas(p,a%m(p),b%m(p))%m(p);
    }
    inline void exgcd(ll a,ll b)
    {
    	if(!b){xx=1,yy=0;return;}
    	exgcd(b,a%b);
    	ll zz=xx;xx=yy;yy=zz-a/b*yy;
    }
    inline ll INV(ll a,ll b)
    {
    	exgcd(a,b);
    	return (xx%b+b)%b;
    }
    inline ll solve(ll a,ll b)
    {
    	rep(1,p,i)ans(i)=Lucas(i,a,b);//,cout<<ans(i)<<endl;
    	if(p==1)return ans(p);
    	//中国剩余定理.
    	ll ans=0;
    	rep(1,p,i)
    	{
    		ll M=mod/m(i);
    		ll ww=INV(M,m(i));
    		ans=(ans+M*ww%mod*ans(i))%mod;
    	}
    	return ans;
    }
    signed main()
    {
    	freopen("1.in","r",stdin);
    	get(n);get(m);get(k);get(mod);
    	if(mod==1000003)m(p=1)=mod;
    	else 
    	{
    		m(p=1)=3;m(p=2)=5;
    		m(p=3)=10007;m(p=4)=6793;
    	}
    	prepare();//cout<<solve(3,2)<<endl;
    	rep(1,k,i){ll get(x);s[i]=(jl){x,read()};}
    	sort(s+1,s+1+k,cmp);
    	s[++k]=(jl){n,m};
    	rep(1,k,i)
    	{
    		f[i]=solve(s[i].x+s[i].y,s[i].x);
    		rep(1,i-1,j)if(s[j].y<=s[i].y)
    			f[i]=(f[i]-f[j]*solve(s[i].x-s[j].x+s[i].y-s[j].y,s[i].x-s[j].x))%mod;
    	}
    	put((f[k]+mod)%mod);return 0; 
    }
    

    又复习了一遍卢卡斯定理 和 中国剩余定理。/ll

  • 相关阅读:
    实现页面切换(动画效果实现,不用ViewPager)
    “仅仅生一个娃”--设计模式中的单例模式
    ZOJ
    【J2SE高速进阶】——多线程之synchronized
    [LeetCode] Search a 2D Matrix II
    leetCode 58.Length of Last Word (最后单词的长度) 解题思路和方法
    [CentOS]怎样解决gcc版本号冲突?
    从0开始学习 GITHUB 系列之「GITHUB 常见的几种操作」【转】
    从0开始学习 GITHUB 系列之「向GITHUB 提交代码」【转】
    从0开始学习 GITHUB 系列之「GIT 速成」【转】
  • 原文地址:https://www.cnblogs.com/chdy/p/12638215.html
Copyright © 2020-2023  润新知