【洛谷比赛】Agent1

前言

报了比赛过后愉快地忘记了它

和家人吃了个火锅,回来发现已经八点多了...只剩2h了。。。

吃饱了过后好难思考问题啊,还是勉强点开了比赛,基础数学大幅度退步,40min才搞定T1

然后看T2,觉得有点像贪心,但是贪心不会放第二题吧,虽然出题人说自己出的题水...考虑资源分配类dp呢?有点像吧

不想思考啊,于是敲了个大法师,敲了一半巨困无比,于是瘫在沙发上睡了一会儿,醒来就只有25min了!!

把T3瞄了一眼,读懂了题,感觉暴力挺好打的,但是状态与状态之间似乎有冲突关系?难道会用一点而并查集??

哎呀算了算了坐等比赛结束...

结局就是只做了第一题

题解

题面

某地的ENLIGHTENED总部总部有N个Agent,每个Agent的能力值互不相同,现在ENLIGHTENED行动指挥想要派出A,B两队Agent去参加XM大战。但是参加大战的两个队伍要满足两个要求:

  1. A队中能力最大的Agent的能力值要小于B队能力最弱的Agent的能力值。
  2. 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;
}

 

posted @ 2018-10-03 23:05  WJEMail  阅读(336)  评论(0编辑  收藏  举报