zoukankan      html  css  js  c++  java
  • UOJ #22 UR #1 外星人

    LINK:#22. UR #1 外星人

    给出n个正整数数 一个初值x x要逐个对这些数字取模 问怎样排列使得最终结果最大 使结果最大的方案数又多少种?

    n<=1000,x<=5000.

    考虑一个排列真正的有效取模只有当 (xgeq a_i)时才行 所以x通过一个排列真正有效的数字必然是从大到小排列的。

    求第一问 不难想到将模数从大到小排列 设f[i][j]表示到达第i个模数此时值为j是否可行。

    这样dp下来我们只需要取出小于minn的那个可行值最大的即可。

    考虑方案数 这样dp同样有效。

    不过复杂度 (n^2cdot x) 比较高。

    考虑优化 不难发现对于f[i][j]来说 如果 j比(a_{i-1})还要小 那么没有必要再把状态传到i-1了 直接让i-1在后面位置中随便选择一个位置即可。

    设状态f[i]表示权值到达i的方案数.

    此时只有<=i的模数才能优影响 且前面的所有模数已经被我们安排好位置了。

    如果选择了一个模数 (a_j) 那么 设w=i%(a_j) 权值在i-1到w+1之间的模数便没用了随便排个位置即可。

    复杂度(nx) 可以通过.(值得一提的是 最后能获得的最大值尽量用标记来判断 因为方案数要取模,(刚好模为0 就脸黑了.

    const int MAXN=5010;
    int n,m,minn;
    int a[MAXN],vis[MAXN],b[MAXN];
    ll f[MAXN],inv[MAXN],fac[MAXN];
    inline ll ksm(ll b,int p){ll cnt=1;while(p){if(p&1)cnt=cnt*b%mod;b=b*b%mod;p=p>>1;}return cnt;}
    inline void prepare()
    {
    	fac[0]=1;
    	rep(1,n,i)fac[i]=fac[i-1]*i%mod;
    	inv[n]=ksm(fac[n],mod-2);
    	fep(n-1,0,i)inv[i]=inv[i+1]*(i+1)%mod;
    }
    int main()
    {
    	freopen("1.in","r",stdin);
    	get(n);get(m);minn=INF;
    	rep(1,n,i)get(a[i]),minn=min(minn,a[i]),++vis[a[i]];
    	rep(1,m,i)vis[i]+=vis[i-1];
    	prepare();f[m]=fac[n]*inv[vis[m]]%mod;
    	sort(a+1,a+1+n);
    	fep(m,1,i)
    	{
    		if(!f[i])continue;
    		rep(1,n,j)
    		{
    			if(a[j]>i)break;
    			f[i%a[j]]=(f[i%a[j]]+f[i]*fac[vis[i]-1]%mod*inv[vis[i%a[j]]])%mod;
    		}
    	}
    	fep(minn-1,0,i)if(f[i]){printf("%d %lld
    ",i,f[i]);return 0;}
    }
    
  • 相关阅读:
    C++模板编译模型
    C++继承与构造函数、复制控制
    PHP判断用户是手机端?还是浏览器端访问?
    CentOS6.5搭建LNMP
    星级评分--封装成jquery插件
    扩展thinkphp5的redis类方法
    js实现星级评分之方法一
    js原型与继承
    一个基于Tp3.2(thinkphp3.2)的工会管理系统
    实验楼的php比赛题,网页数据提取。
  • 原文地址:https://www.cnblogs.com/chdy/p/12599956.html
Copyright © 2011-2022 走看看