zoukankan      html  css  js  c++  java
  • [六省联考2017]分手是祝愿(期望DP)

    [六省联考2017]分手是祝愿(期望DP)

    题面

    分析

    先考虑初始状态灭掉所有灯的最小次数(cnt),可以从大到小贪心求出。因为每个灯只能被比它大的更新,可以直接从大到小,遇到开的就按灭,同时操作它的约数。复杂度(O(nlog n))

    如果(cnt leq k),那么只需要初始时按最小次数操作即可,输出(n!cdot cnt)
    否则需要期望DP.容易发现,每个开关都不能被其他开关的组合替代。设(f_i)表示把需要按(i)个正确的开关(可能有重复)来灭掉所有灯的状态转化为需要按(i-1)个正确的开关的期望次数。那么有:

    [f_i=frac{i}{n}+frac{n-i}{n}(f_i+f_{i+1}+1) ]

    因为随机选有可能操作(i)个正确的开关,也可能操作错误的开关,那么就需要再按一次抵消这次操作,需要的开关数变成(i+1),再变回(i),因此加上(f_i+f_{i+1})

    移项得到递推方程,边界(f_n=1)

    [f_i=1+frac{(1*n-i)*(f_{i+1}+1)}{i} ]

    最终答案(n!(k+sum_{j=k+1}^{cnt} f_j))

    代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<vector>
    #define mod 100003
    #define maxn 100000
    using namespace std;
    typedef long long ll;
    inline ll fast_pow(ll x,ll k){
    	ll ans=1;
    	while(k){
    		if(k&1) ans=ans*x%mod;
    		x=x*x%mod;
    		k>>=1;
    	} 
    	return ans;
    } 
    inline ll inv(ll x){
    	return fast_pow(x,mod-2);
    }
    int n,k;
    vector<int>d[maxn+5]; 
    int a[maxn+5];
    
    ll fact[maxn+5],invfact[maxn+5],invx[maxn+5];
    ll dp[maxn+5];
    void ini(int n){
    	fact[0]=1;
    	for(int i=1;i<=n;i++) fact[i]=fact[i-1]*i%mod;
    	invfact[n]=inv(fact[n]);
    	for(int i=n-1;i>=0;i--) invfact[i]=invfact[i+1]*(i+1)%mod;
    	for(int i=1;i<=n;i++) invx[i]=fact[i-1]*invfact[i];
    }
    int main(){
    	scanf("%d %d",&n,&k);
    	ini(n);
    	for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    	for(int i=1;i<=n;i++){
    		for(int j=i;j<=n;j+=i) d[j].push_back(i);
    	}
    	int mina=0;//贪心得出的最小次数 
    	for(int i=n;i>=1;i--){
    		if(a[i]){
    			for(int j=0;j<(int)d[i].size();j++) a[d[i][j]]^=1;
    			mina++;
    		}
    	}
    	dp[n]=1;
    	for(int i=n-1;i>=1;i--){
    		dp[i]=(1+(n-i)*(dp[i+1]+1)%mod*invx[i]%mod)%mod; 
    	}
    	if(mina<=k) printf("%lld
    ",mina*fact[n]%mod);//初始局面的答案就<=k,直接操作
    	else{
    		ll ans=0;
    		for(int i=mina;i>=k+1;i--) ans=(ans+dp[i])%mod;//从mina到mina-1,mina-2....k
    		ans=(ans+k)%mod;
    		printf("%lld
    ",ans*fact[n]%mod); 
    	} 
    	
    }
    
  • 相关阅读:
    171. Excel Sheet Column Number (Easy)
    349. Intersection of Two Arrays (Easy)
    453. Minimum Moves to Equal Array Elements (Easy)
    657. Judge Route Circle (Easy)
    CSS笔记
    保存页面状态
    UI开发总结
    ubuntu 下配置munin
    反向代理配置
    JavaScript 高级程序设计第二版
  • 原文地址:https://www.cnblogs.com/birchtree/p/12952827.html
Copyright © 2011-2022 走看看