zoukankan      html  css  js  c++  java
  • agc005D ~K Perm Counting

    题意:有多少排列对于每个位置$i$都满足$|a_i-i| e k$

    $k < n leq 2000$

    一道简单的容斥+dp。事实证明,我做题思考的时候要靠感觉不能靠兴趣。

    一开始就感觉应该是每个同余类分别dp,然后再合起来就可以了。

    求出有i个位置是不合法的值,其他位置不确定,的方案数。最后容斥。

    但是后来总是想把这道题往图论上面靠,就把NicoDafaGood带偏了。

    dp写得比较拙劣

    //Serene
    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<cmath>
    using namespace std;
    #define ll long long
    #define db double
    #define For(i,a,b) for(int i=(a);i<=(b);++i)
    #define Rep(i,a,b) for(int i=(a);i>=(b);--i)
    const int maxn=2000+7;
    const ll mod=924844033;
    ll n,K,sum[maxn],mi[maxn],ans;
    ll f[2][maxn][maxn][4],dp[maxn][maxn];
    
    template<typename T>void read(T& aa) {
    	aa=0;char cc=getchar();T ff=1;
    	while((cc!='-')&&(cc<'0'||cc>'9')) cc=getchar();
    	if(cc=='-') ff=-1,cc=getchar();
    	while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
    	aa*=ff;
    }
    
    void get_dp(int n,int o) {
    	f[o][0][0][1]=1;
    	For(i,0,n-1) For(j,0,i) For(k,0,3) {
    		if(!f[o][i][j][k]) continue;
    		f[o][i][j][k]%=mod;
    		f[o][i+1][j][k>>1]+=f[o][i][j][k];
    		if((k&1)==0) f[o][i+1][j+1][k>>1]+=f[o][i][j][k];
    		if(i!=n-1) f[o][i+1][j+1][(k>>1)+2]+=f[o][i][j][k];
    	}
    	For(i,0,n) {
    		For(j,1,3) f[o][n][i][0]+=f[o][n][i][j];
    		f[o][n][i][0]%=mod;
    	}
    }
    
    int main() {
    	read(n); read(K); int x,y;
    	mi[0]=1; For(i,1,n) mi[i]=mi[i-1]*(ll)i%mod;
    	For(i,1,K) sum[i]=(n-i)/K+1;
    	get_dp(sum[K],0);
    	if(sum[1]>sum[K]) get_dp(sum[1],1);
    	dp[0][0]=1;
    	For(i,1,K) {
    		For(j,0,sum[i-1]) if(dp[i-1][j]) {
    			x=sum[i]; y=x-sum[K];
    			For(k,0,x) dp[i][j+k]+=dp[i-1][j]*f[y][x][k][0]%mod;
    		}
    		sum[i]+=sum[i-1];
    		For(j,0,sum[i]) dp[i][j]%=mod;
    	}
    	For(i,0,n) dp[K][i]=dp[K][i]*mi[n-i]%mod;
    	For(i,0,n) {
    		if(i&1) ans+=mod-dp[K][i];
    		else ans+=dp[K][i];
    	}
    	printf("%lld
    ",ans%mod);
    	return 0;
    }
  • 相关阅读:
    资源
    p/invoke碎片,对结构体的处理
    p/invoke碎片--对数组的封送处理
    p/invoke碎片--对类的封送处理
    CSS--background
    在Main方法中设置异常的最后一次捕捉
    记一次WinForm中屏蔽空格键对按钮的作用
    记一次WinForm程序中主进程打开子进程并传递参数的操作过程(进程间传递参数)
    知识点
    安卓N特性
  • 原文地址:https://www.cnblogs.com/Serene-shixinyi/p/9237744.html
Copyright © 2011-2022 走看看