zoukankan      html  css  js  c++  java
  • LOJ6374[SDWC2018 Day1]网格

    LOJ6374[SDWC2018 Day1]网格

    题面:LOJ

    解析

    这是大佬的题解

    先考虑没有任何限制的情况,发现可以将两维分开来看,考虑容斥解决掉步长限制,设(g(i))表示至少(i)步超过限制的方案数,那么有:

    [g(i)={R choose i}{T_x-i imes(M_x+1)+R-1 choose R-1} ]

    就是保证(i)步超出限制,然后剩下的步数随意分配即可。
    那么容斥可得:

    [Ans=sum_{i=0}^{R}(-1)^{i} g(i) ]

    那么我们可以将二维答案合并起来,就有:(Ans=Ans_x imes Ans_y)
    但是这样的答案中有停留在原地的步数,所以其实是至多走了(R)步的方案数。
    再一次考虑容斥消去影响,设(g(i))表示至多走(i)步的方案数,(f(i))表示恰好走(i)步的方案数,那么有:

    [g(R)=Ans_x imes Ans_y=sum_{i=0}^{R} {R choose i}f(i) ]

    二项式反演,得:

    [f(R)=sum_{i=0}^{R}(-1)^{R-i}{R choose i}g(i) ]

    那么分别计算(g(i))统计答案即可。
    但是题目中还有其他限制,不能走某些步长,再一次考虑容斥统计答案,设(g(i))表示至少违规移动(i)步的方案数,(f(i))表示恰好违规移动(i)步的方案数,那么有:

    [Ans=f(0)=sum_{i=0}^{lim}(-1)^{i}g(i) ]

    考虑如何计算(g(i)):因为是至少,大概就是强制(i)步违规乘上剩下步数随意走的方案数,发现随意走的方案数可以用上面的方法(O(R^{2}))计算,我们现在只用考虑如何计算强制(i)步违规的方案数了,设(S(i,j))表示违规走(i)步,违规走的步长和为(j)的方案数,发现(j)(G)的倍数,因此可以记录(frac{j}{G}),而最多违规移动的步数最多(lim=frac{1e6}{1e4}=100),这样(S(i,j))的状态就只有(O(lim^2))种,可以(O(lim^3))提前预处理出来。
    那么有:

    [g(i)=sum_{j}S(i,j) imes Calc(T_x-j imes G,T_y-j imes G,Mx,My,R-i){R choose i} ]

    计算出(g(i))就可以算出真正的答案了。复杂度是多少呢?
    发现(g(i))最多有(O(lim))种,而计算一次(g(i))的复杂度为(O(lim imes i^2)),那么总复杂度就是(O(lim^2 R^2))PS:这复杂度感觉过不了啊,常数小?如果算错了,请大佬指出错误。

    代码

    
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    const int P=1e9+7,N=1e6;
    inline int In(){
    	char c=getchar(); int x=0,ft=1;
    	for(;c<'0'||c>'9';c=getchar()) if(c=='-') ft=-1;
    	for(;c>='0'&&c<='9';c=getchar()) x=x*10+c-'0';
    	return x*ft;
    }
    int k[55],fac[N+5],inv[N+5],S[105][105],ans=0;
    inline int power(int x,int r){
    	int s=1,t=x;
    	for(;r;r>>=1,t=1ll*t*t%P) if(r&1) s=1ll*s*t%P;
    	return s;
    }
    inline int C(int m,int n){
    	if(m<n) return 0;
    	return 1ll*fac[m]*inv[n]%P*inv[m-n]%P;
    }
    inline int g(int T,int M,int R){
    	int res=0;
    	for(int i=0,d=1;i<=R;++i,d=P-d)
    	res=(res+1ll*d*C(R,i)%P*C(T-i*(M+1)+R-1,R-1)%P)%P;
    	return res;
    }
    int Calc(int Tx,int Ty,int Mx,int My,int R){
    	int res=0;
    	for(int i=0,d=(R&1?P-1:1);i<=R;++i,d=P-d)
    	res=(res+1ll*d*C(R,i)%P*g(Tx,Mx,i)%P*g(Ty,My,i)%P)%P;
    	return res;
    }
    int main(){
    	int Tx=In(),Ty=In(),Mx=In(),My=In(),R=In();
    	int G=In(),K=In(),lim=(Tx<Ty?Tx:Ty)/G;
    	for(int i=1;i<=K;++i) k[i]=In(),k[i]/=G;
    	sort(k+1,k+1+K); K=unique(k+1,k+1+K)-k-1;
    	fac[0]=1;
    	for(int i=1;i<=N;++i) fac[i]=1ll*fac[i-1]*i%P;
    	inv[N]=power(fac[N],P-2);
    	for(int i=N-1;~i;--i) inv[i]=1ll*inv[i+1]*(i+1)%P;
    	S[0][0]=1;
    	for(int i=0;i<R&&i<lim;++i)
    	for(int j=0;j<=lim;++j) if(S[i][j])
    	for(int t=1;t<=K;++t)
    	S[i+1][j+k[t]]=(S[i+1][j+k[t]]+S[i][j])%P;
    	for(int i=0,d=1;i<=R&&i<=lim;++i,d=P-d)
    	for(int j=i;j<=lim;++j) if(S[i][j]){
    		ans=(ans+1ll*d*S[i][j]%P*Calc(Tx-j*G,Ty-j*G,Mx,My,R-i)%P*C(R,i)%P)%P;
    	}
    	printf("%d
    ",ans);
    	return 0;
    }
    
    
  • 相关阅读:
    mysql 分库分表
    策略模式
    JAVA NIO 选择器
    有关于web server架构的一个小疑问
    Android 吸入动画效果详解
    android中设置TextView/Button 走马灯效果
    浅谈Jquery的使用上篇
    ORA-00376:file x cannot be read at this time
    用VBA宏从一个工作薄复制内容到另一个工作薄
    ovirt node的安装简介
  • 原文地址:https://www.cnblogs.com/pkh68/p/10549078.html
Copyright © 2011-2022 走看看