【洛谷比赛】Agent1
前言
报了比赛过后愉快地忘记了它
和家人吃了个火锅,回来发现已经八点多了...只剩2h了。。。
吃饱了过后好难思考问题啊,还是勉强点开了比赛,基础数学大幅度退步,40min才搞定T1
然后看T2,觉得有点像贪心,但是贪心不会放第二题吧,虽然出题人说自己出的题水...考虑资源分配类dp呢?有点像吧
不想思考啊,于是敲了个大法师,敲了一半巨困无比,于是瘫在沙发上睡了一会儿,醒来就只有25min了!!
把T3瞄了一眼,读懂了题,感觉暴力挺好打的,但是状态与状态之间似乎有冲突关系?难道会用一点而并查集??
哎呀算了算了坐等比赛结束...
结局就是只做了第一题
题解
题面
某地的ENLIGHTENED总部
总部有N个Agent
,每个Agent
的能力值互不相同,现在ENLIGHTENED行动指挥
想要派出A,B两队Agent
去参加XM大战
。但是参加大战的两个队伍要满足两个要求:
- A队中能力最大的
Agent
的能力值要小于B队能力最弱的Agent
的能力值。 - A,B两队都要有人参战。
并不一定所有的Agent
都要去参加XM大战
的,心急的ENLIGHTENED行动指挥
想知道有多少种安排Agent
参加大战的方案。由于答案可能很大,所以只需要你求出答案模(10^9+7)的值就可以了。
分析
不是很难,我做题的过程是 找规律-->打表验证规律-->化简公式(消除递推项)
就设这N个值分别是1~N,先看看样例
N==1:无合法情况
N==2:①A:1 B:2
N==3:①A:1 B:2 ②A:1 B:3 2 ③A:1 B:3 ④A:2 B:3 ⑤A:2 1 B:3
可以发现,其实如果每次考虑插入一个最大的数k进来,首先,k-1时的所有方案是都合法的(不需要全部用完)
而k-1时的所有方案的B集合里添加一个k,也是合法的
如上面N==3的时候的第1组和第2组
那继续接着N==3讨论,剩下那三组是什么呢?你会发现,其实就是在1,2两个数中选一个或选两个,这不就是组合数求和吗!
众所周知 C(n,0)+C(n,1)+C(n,2)+……+C(n,n)=2^n,C(n,0)=1,所以C(n,1)+C(n,2)+……+C(n,n)=2^n -1
推广出去,就可以得到f[n]=f[n-1]*2+2^n-1 (n>=2),f[1]=0.
然而数据规模达到了1e9,递推是不行的,就只有把递推式化简成通项公式。对于我这个数学渣来说内心是拒绝的aaa....
还是得硬着头皮化。于是用上了我在数列里最爱搞的一套枚举,我模拟了f[4]的计算方法,就推出来了
f[4]=f[3]*2+23-1=(f[2]*2+22-1)*2+23-1=(((f[1]*2+21-1))*2+22-1)+23-1=4*(21-1)+2*(22-1)+23-1
=3*23-(1+2+4)
推广出去 f[n]=(n-1)*2(n-1)-(1+2+…+2n-1)
后面这一堆减的数再用等比数列求个和
然后就可以化成 最后最简的式 f[n]=(n-2)*2(n-1)+1
最后快速幂一下,就OK了
#include<bits/stdc++.h> using namespace std; #define mod 1000000007 #define ll long long ll n; ll ksm(ll a,ll b) { ll ret=1; while(b) { if(b&1)ret=(ret*a)%mod; a=(a*a)%mod; b>>=1; } return ret; } int main() { cin>>n; cout<<((n-2)*ksm(2,n-1))%mod+1; return 0; }