Description:
1 < = T < = 1 0 5 , 1 < = k , m < = n < = 1 0 6 1<=T<=10^5,1<=k,m<=n<=10^6 1<=T<=105,1<=k,m<=n<=106
题解:
这题很好的考察了观察能力、组合数乱搞能力,然后我被区分了。
首先假设选了一些点,它们是
a
1
,
a
2
,
a
3
…
…
a
m
a1,a2,a3……am
a1,a2,a3……am,根据圆周角那一套东西,
锐角的个数
=
∑
i
=
1
n
a
[
i
+
2
]
−
>
a
[
i
]
>
=
(
n
+
1
)
/
2
=\sum_{i=1}^n a[i+2]->a[i]>=(n+1)/2
=∑i=1na[i+2]−>a[i]>=(n+1)/2
也可以变成:
选一个长度为m的序列
b
b
b,
b
[
i
]
>
0
,
∑
b
[
i
]
=
n
b[i]>0,\sum b[i]=n
b[i]>0,∑b[i]=n,
锐角的个数
=
∑
i
=
1
n
b
[
i
]
+
b
[
i
+
1
]
>
=
(
n
+
1
)
/
2
=\sum_{i=1}^nb[i]+b[i+1]>=(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)=Cn−1m−1,显然。
s
(
1
)
s(1)
s(1)的话枚举一个点x,
假设
a
[
x
]
+
a
[
x
+
1
]
>
=
p
a[x]+a[x+1]>=p
a[x]+a[x+1]>=p
1.
a
[
x
]
<
=
p
−
1
1.a[x]<=p-1
1.a[x]<=p−1
设
a
[
x
]
=
h
a[x]=h
a[x]=h则
a
[
x
+
1
]
>
=
p
−
h
a[x+1]>=p-h
a[x+1]>=p−h
视作先把 a [ x − 1 ] a[x-1] a[x−1]减了一个 p − h − 1 p-h-1 p−h−1,把a[x]剃掉
= C n − ( p − 1 ) − 1 m − 2 ∗ ( p − 1 ) =C_{n-(p-1)-1}^{m-2}*(p-1) =Cn−(p−1)−1m−2∗(p−1)
2.
a
[
x
]
>
=
p
2.a[x]>=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−(p−1)−1m−1
发现三个必须相邻
设为
a
[
x
−
1
]
,
a
[
x
]
,
a
[
x
+
1
]
a[x-1],a[x],a[x+1]
a[x−1],a[x],a[x+1]
1.
1.
1.
a
[
x
]
<
=
p
−
1
a[x]<=p-1
a[x]<=p−1
道理相同,设
a
[
x
]
=
h
a[x]=h
a[x]=h,则
a
[
x
−
1
]
,
a
[
x
+
1
]
>
=
p
−
h
a[x-1],a[x+1]>=p-h
a[x−1],a[x+1]>=p−h
视作减掉 2 ∗ ( p − h − 1 ) 2*(p-h-1) 2∗(p−h−1)
=
∑
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=1p−1Cn−2∗(p−h−1)−h−1m−2
=
∑
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=1p−1Cn−2∗p+2−1+hm−2
我们有:
∑
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]=p−h,则
=
C
n
−
p
+
2
−
1
m
−
1
=C_{n-p+2-1}^{m-1}
=Cn−p+2−1m−1
2.
a
[
m
]
>
=
p
2.a[m]>=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);
}
}