【北大2019冬令营模拟2019.1.1】多边形

Description:

在这里插入图片描述

1 &lt; = T &lt; = 1 0 5 , 1 &lt; = k , m &lt; = n &lt; = 1 0 6 1&lt;=T&lt;=10^5,1&lt;=k,m&lt;=n&lt;=10^6 1<=T<=105,1<=k,m<=n<=106

题解:

这题很好的考察了观察能力、组合数乱搞能力,然后我被区分了。

首先假设选了一些点,它们是 a 1 , a 2 , a 3 … … a m a1,a2,a3……am a1,a2,a3am,根据圆周角那一套东西,
锐角的个数 = ∑ i = 1 n a [ i + 2 ] − &gt; a [ i ] &gt; = ( n + 1 ) / 2 =\sum_{i=1}^n a[i+2]-&gt;a[i]&gt;=(n+1)/2 =i=1na[i+2]>a[i]>=(n+1)/2

也可以变成:
选一个长度为m的序列 b b b b [ i ] &gt; 0 , ∑ b [ i ] = n b[i]&gt;0,\sum b[i]=n b[i]>0,b[i]=n
锐角的个数 = ∑ i = 1 n b [ i ] + b [ i + 1 ] &gt; = ( n + 1 ) / 2 =\sum_{i=1}^nb[i]+b[i+1]&gt;=(n+1)/2 =i=1nb[i]+b[i+1]>=(n+1)/2
这样的b的个数*n/m就是答案,为什么呢?

b实际上枚举的是差分后的序列,每个点都可以作为起点, ∗ n *n n,然后每个点被覆盖了n*m/n=m次
所以会重复计算m次。

直接算不好算,然后我们考虑容斥,算至少的,用二项式反演容斥回去就行了。

p = ( n + 1 ) / 2 p=(n+1)/2 p=(n+1)/2
s ( i ) s(i) s(i)表示至少i个锐角的。


s ( 0 ) = C n − 1 m − 1 s(0)=C_{n-1}^{m-1} s(0)=Cn1m1,显然。


s ( 1 ) s(1) s(1)的话枚举一个点x,
假设 a [ x ] + a [ x + 1 ] &gt; = p a[x]+a[x+1]&gt;=p a[x]+a[x+1]>=p

1. a [ x ] &lt; = p − 1 1.a[x]&lt;=p-1 1.a[x]<=p1
a [ x ] = h a[x]=h a[x]=h a [ x + 1 ] &gt; = p − h a[x+1]&gt;=p-h a[x+1]>=ph

视作先把 a [ x − 1 ] a[x-1] a[x1]减了一个 p − h − 1 p-h-1 ph1,把a[x]剃掉

= C n − ( p − 1 ) − 1 m − 2 ∗ ( p − 1 ) =C_{n-(p-1)-1}^{m-2}*(p-1) =Cn(p1)1m2(p1)

2. a [ x ] &gt; = p 2.a[x]&gt;=p 2.a[x]>=p
那么先把 a [ x ] a[x] a[x]减掉一个(p-1)就行了。

= C n − ( p − 1 ) − 1 m − 1 =C_{n-(p-1)-1}^{m-1} =Cn(p1)1m1


发现三个必须相邻
设为 a [ x − 1 ] , a [ x ] , a [ x + 1 ] a[x-1],a[x],a[x+1] a[x1],a[x],a[x+1]

1. 1. 1. a [ x ] &lt; = p − 1 a[x]&lt;=p-1 a[x]<=p1
道理相同,设 a [ x ] = h a[x]=h a[x]=h,则 a [ x − 1 ] , a [ x + 1 ] &gt; = p − h a[x-1],a[x+1]&gt;=p-h a[x1],a[x+1]>=ph

视作减掉 2 ∗ ( p − h − 1 ) 2*(p-h-1) 2(ph1)

= ∑ h = 1 p − 1 C n − 2 ∗ ( p − h − 1 ) − h − 1 m − 2 =\sum_{h=1}^{p-1}C_{n-2*(p-h-1)-h-1}^{m-2} =h=1p1Cn2(ph1)h1m2
= ∑ h = 1 p − 1 C n − 2 ∗ p + 2 − 1 + h m − 2 =\sum_{h=1}^{p-1}C_{n-2*p+2-1+h}^{m-2} =h=1p1Cn2p+21+hm2

我们有: ∑ i = 0 a C i b = C a + 1 b + 1 \sum_{i=0}^aC_{i}^b=C_{a+1}^{b+1} i=0aCib=Ca+1b+1,类似的:
考虑意义,补一个 a [ m ] = p − h a[m]=p-h a[m]=ph,则 = C n − p + 2 − 1 m − 1 =C_{n-p+2-1}^{m-1} =Cnp+21m1

2. a [ m ] &gt; = p 2.a[m]&gt;=p 2.a[m]>=p
同上的2


发现只有m=3才有解,并且是m=2的1情况。

end.

Code:

#include<cstdio>
#define pr printf
#define ll long long
#define fo(i, x, y) for(int i = x; i <= y; i ++)
#define fd(i, x, y) for(int i = x; i >= y; i --)
using namespace std;

const int N = 1e6 + 5;

int T, n, m, k, ans;
ll fac[N], nf[N];

const int mo = 1000109107;

ll ksm(ll x, ll y) {
	ll s = 1;
	for(; y; y /= 2, x = x * x % mo)
		if(y & 1) s = s * x % mo;
	return s;
}

ll C(int n, int m) {
	if(n < m || n < 0 || m < 0) return 0;
	return fac[n] * nf[m] % mo * nf[n - m] % mo;
}

ll f[4];

ll s(int k) {
	int p = n + 1 >> 1;
	int x = n / 2;
	if(k == 0) {
		return C(n - 1, m - 1);
	} else
	if(k == 1) {
		return (C(n - p, m - 2) * (p - 1) % mo + C(n - p, m - 1)) % mo * m % mo;
	} else
	if(k == 2) {
		return (C(n - p + 1, m - 1) + C(n - p, m - 1)) % mo * m % mo;
	} else {
		if(m != 3) return 0;
		return C(n - p + 1, m - 1) % mo;
	}
}

int main() {
	freopen("polygon.in", "r", stdin);
	freopen("polygon.out", "w", stdout);
	n = 1e6;
	fac[0] = 1; fo(i, 1, n) fac[i] = fac[i - 1] * i % mo;
	nf[n] = ksm(fac[n], mo - 2); fd(i, n, 1) nf[i - 1] = nf[i] * i % mo;
	scanf("%d", &T);
	fo(ii, 1, T) {
		scanf("%d %d %d", &n, &m, &k);
		if(k > 3) { pr("0\n"); continue;}
		ll ans = 0;
		fo(i, k, 3) ans += (i - k & 1 ? -1 : 1) * C(i, k) * s(i) % mo;
		ans = (ans % mo * n % mo * ksm(m, mo - 2) % mo + mo) % mo;
		pr("%lld\n", ans);
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值