码迷,mamicode.com
首页 > 其他好文 > 详细

agc045_d Lamps and Buttons

时间:2020-06-29 18:39:34      阅读:107      评论:0      收藏:0      [点我收藏+]

标签:har   display   getc   ons   const   ati   增加   a+b   button   

agc045_d Lamps and Buttons

https://atcoder.jp/contests/agc045/tasks/agc045_d

技术图片

Tutorial

考虑Snuke的策略.

从小到大一次枚举 \(i\) ,按下 \(i\) ,如果 \(p_i=i\) ,则失败,否则可以点亮 \(i\) 所在的环.如果某次操作后所有灯都是亮的,则胜利,结束游戏.

本质上的原因是,枚举 \(i\) 的顺序对于获胜的概率没有影响.

所以,设 \(t\)\([1,A]\) 最小的位置使得 \(p_t=t\) (若不存在,则 \(t=A+1\)).那么获胜的条件就是,对于所有\(i \in [A+1,N]\),存在\(x\in [1,t)\)使得\(x\)\(i\)所属环内.

由于需要保证\(t\)的最小性,所以需要增加一步容斥.

现在的问题相当于,要找到一个\(a+b+c\)的排列,满足对于\(i\in[a+1,a+b]\),存在一个\(x\in[1,a]\)使得\(x\)\(i\)的环内

\[a! \cdot \dfrac {(a+b-1)!}{(a-1)!} \cdot \dfrac {(a+b+c)!}{(a+b)!} = (a+b+c)! \cdot \dfrac a{a+b} \]

复杂度 \(O(A^2+N)\)

Code

#include <cstdio>
#include <iostream>
#define debug(...) fprintf(stderr,__VA_ARGS__)
#define inver(a) power(a,mod-2)
#define upd(a,b) a=add(a+b)
#define INV(a) ((ll)inv[a]*fac[a-1]%mod)
using namespace std;
inline char gc() {
//	return getchar();
	static char buf[100000],*l=buf,*r=buf;
	return l==r&&(r=(l=buf)+fread(buf,1,100000,stdin),l==r)?EOF:*l++;
}
template<class T> void rd(T &x) {
	x=0; int f=1,ch=gc();
	while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=gc();}
	while(ch>=‘0‘&&ch<=‘9‘){x=x*10-‘0‘+ch;ch=gc();}
	x*=f;
}
typedef long long ll;
const int mod=1e9+7;
const int maxn=1e7+50;
const int maxA=5000+5;
int n,A;
int fac[maxn],inv[maxn];
inline int add(int x) {return x>=mod?x-mod:x;}
inline int sub(int x) {return x<0?x+mod:x;}
ll power(ll x,ll y) {
	ll re=1;
	while(y) {
		if(y&1) re=re*x%mod;
		x=x*x%mod;
		y>>=1;
	}
	return re;
}
inline int binom(int x,int y) {
	return (ll)fac[x]*inv[y]%mod*inv[x-y]%mod;
}
inline int cal(int a,int b,int c) {
	return (ll)fac[a+b+c]*a%mod*INV(a+b)%mod;
}
void init(int n) {
	fac[0]=1;
	for(int i=1;i<=n;++i) fac[i]=(ll)fac[i-1]*i%mod;
	inv[n]=inver(fac[n]);
	for(int i=n;i>=1;--i) inv[i-1]=(ll)inv[i]*i%mod;
}
int main() {
	rd(n),rd(A);
	init(n);
	int an=0;
	for(int t=1;t<=A+1;++t) {
		for(int j=0,f=1;j<t;++j,f=mod-f) {
			an=(an+(ll)cal(t-j-1,n-A,max(0,A-t))*binom(t-1,j)%mod*f)%mod;
		}
	}
	printf("%d\n",an);
	return 0;
}

agc045_d Lamps and Buttons

标签:har   display   getc   ons   const   ati   增加   a+b   button   

原文地址:https://www.cnblogs.com/ljzalc1022/p/13209520.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!