• Codeforces 1437F Emotional Fishermen(思维,dp)


    题意

    给出数列\(a_i\),求排列\(p_i\)的数量满足

    \[\frac{a_{p_i}}{max_{j=1}^{i-1}a_{p_j}} \notin (\frac{1}{2},2) \]

    思路

    数列可以按前缀最大值相同划分为几个连续段,不妨设第\(i\)段开头(即前缀最大值)为\(m_i\),满足\(2m_i \leq m_{i+1}\),第\(i\)段内元素\(x\)满足\(2x \leq m_i\),

    于是有一个\(dp\)做法,\(dp_i\)表示当前段开头为\(a_i\),枚举上一段的开头\(a_j\),将\(a_i\)放在当前的第一个空位中,对于所有\(2a_j \leq a_i\),有序填入剩余空位中。

    我们有转移方程

    \[dp_i = \sum dp_j\cdot A(n-2-pre_j,pre_i-pre_j-1) \]

    其中\(pre_i\)表示\(2a_j \leq a_i\) 的个数,\(n-2-pre_j\)表示剩余空位,\(-2\)去掉了\(a_i,a_j\)\(pre_i-pre_j-1\)表示当前可用的,\(-1\)去掉了\(a_j\)

    代码

    #include<bits/stdc++.h>
    #define int long long
    #define N 5005
    #define mod 998244353
    #define rep(i,a,n) for (int i=a;i<=n;i++)
    #define per(i,a,n) for (int i=n;i>=a;i--)
    #define inf 0x3f3f3f3f
    #define pb push_back
    #define mp make_pair
    #define pii pair<int,int>
    #define fi first
    #define se second
    #define lowbit(i) ((i)&(-i))
    #define VI vector<int>
    #define all(x) x.begin(),x.end()
    using namespace std;
    int qpow(int a,int b){
    	int res = 1;
    	while(b){
    		if(b&1) res = (res*a)%mod;
    		a = (a*a)%mod;
    		b >>= 1;
    	}
    	return res;
    }
    int fac[N],inv[N];
    int A(int n,int m){
    	if(n<0 || m<0 || n<m) return 0;
    	return (fac[n]*inv[n-m])%mod;
    }
    int n,a[N],pre[N],dp[N];
    signed main(){
    	//freopen(".in","r",stdin);
    	//freopen(".out","w",stdout);
     	scanf("%lld",&n);
     	rep(i,1,n) scanf("%lld",&a[i]);
     	fac[0] = inv[0] = 1;
     	rep(i,1,n) fac[i] = (fac[i-1]*i)%mod;
     	rep(i,1,n) inv[i] = (qpow(fac[i],mod-2))%mod;
     	sort(a+1,a+n+1);
     	int p = 0;
     	rep(i,1,n){
     		while(p+1 < i && a[p+1]*2 <= a[i]) p++;
     		pre[i] = p;
     	}
     	
     	dp[0] = 1; pre[0] = -1;
     	rep(i,1,n){
     		rep(j,0,pre[i]){
     			dp[i] = (dp[i]+dp[j]*A(n-pre[j]-2,pre[i]-pre[j]-1)%mod)%mod;
     		}
     	}
     	// rep(i,1,n) printf("%lld ",dp[i]);
     	// puts("");
     	if(pre[n] != n-1) puts("0");
     	else printf("%lld",dp[n]);
    	return 0;
    }
    

    事实上可以前缀和优化做到\(O(n)\)

  • 相关阅读:
    WPF之感触
    C# WinForm 给DataTable中指定位置添加列
    MyEclipse 8.6 download 官方下载地址
    将博客搬至CSDN
    Building Microservices with Spring Cloud
    Building Microservices with Spring Cloud
    Building Microservices with Spring Cloud
    Building Microservices with Spring Cloud
    Building Microservices with Spring Cloud
    Building Microservices with Spring Cloud
  • 原文地址:https://www.cnblogs.com/czdzx/p/14032646.html
Copyright © 2020-2023  润新知