zoukankan      html  css  js  c++  java
  • P6672[清华集训2016]你的生命已如风中残烛【结论】

    正题

    题目链接:https://www.luogu.com.cn/problem/P6672


    题目大意

    长度为\(m\)的序列\(a\),有\(n\)个数字不是\(0\),其他\(m-n\)个是\(0\)。要求重排后有多少方案满足

    \[\forall x,\sum_{i=1}^xa_i\geq i \]

    其中\(m=\sum_{i=1}^{n}a_i\)

    \(1\leq n\leq 40,1\leq a_i\leq 10^5\)


    解题思路

    具体数学P301页有一个\(Reney\)引理(虽然我还没看到):
    假设一个整数序列何为\(1\),那么它的所有循环位移中有且仅有一个满足所有的前缀和为\(+1\)

    然后考虑这题,都减去一的话就是要求都为非负了,而且所有数的和为\(0\)

    怎么转换成上面那种情况,加一个进去\(1\)的话不是很行,因为有很多正数所以我们不能保证这个\(1\)排在最前面。

    反着考虑,把所有数取反再加一个\(1\)的话就可以了,因为这样正数就只有\(1\)了。

    所以的话它的圆排列个数就是\(m!\)个了,但是多了一个\(-1\)我们要减去这个\(-1\)的影响,其实就是多塞一个\(-1\)进去的话,就是多了\(m-n+1\)个了。所以答案就是

    \[\frac{m!}{m-n+1} \]


    code

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define ll long long
    using namespace std;
    const ll P=998244353;
    ll n,m,ans;
    ll power(ll x,ll b){
    	ll ans=1;
    	while(b){
    		if(b&1)ans=ans*x%P;
    		x=x*x%P;b>>=1;
    	}
    	return ans;
    }
    signed main()
    {
    	scanf("%lld",&n);
    	for(ll i=1;i<=n;i++){
    		ll x;scanf("%lld",&x);
    		m+=x;
    	}
    	ans=1;
    	for(ll i=1;i<=m;i++)ans=ans*i%P;
    	printf("%lld\n",ans*power(m-n+1,P-2)%P);
    	return 0;
    }
    
  • 相关阅读:
    第一阶段SCRUM冲刺day07
    第一阶段SCRUM冲刺day06
    第一阶段SCRUM冲刺day05
    第一阶段SCRUM冲刺day04
    2020年第七周学习进度
    第一阶段SCRUM冲刺day03
    第一阶段SCRUM冲刺day02
    团队会议01
    2020年第六周学习进度
    TCP/IP Socket 的理解
  • 原文地址:https://www.cnblogs.com/QuantAsk/p/14612575.html
Copyright © 2011-2022 走看看