您的位置:首页 > 其它

B君的宴请

2017-01-20 16:42 176 查看

题目描述



旋转

考虑只旋转。

如果旋转i下,容易知道形成(n,i)个环,每个环大小为n/(n,i),而我们需要k个,因此需要选k(n,i)/n个,在(n,i)个里,且必须互不相邻(包括首尾),这个可以考虑组合数算。

一般化,长度为n的环选出k个不相邻,考虑把n-k个数塞进k个数里,两两间必须塞至少一个,然后讨论最前至少塞1个最后不塞最前不塞最后至少塞1个以及最前最后都至少塞一个,鸽笼原理组合数即可。

翻转

同时有翻转和旋转时,其实可以不理会旋转,然后就是任做一条对称轴。

根据n、k的奇偶性进行讨论,比较容易,详见代码。

#include<cstdio>
#include<algorithm>
#define fo(i,a,b) for(i=a;i<=b;i++)
#define fd(i,a,b) for(i=a;i>=b;i--)
using namespace std;
typedef long long ll;
const int maxn=1000000+10,mo=1000000007;
int fac[maxn],inv[maxn];
int i,j,k,l,t,n,m,ans;
int quicksortmi(int x,int y){
if (!y) return 1;
int t=quicksortmi(x,y/2);
t=(ll)t*t%mo;
if (y%2) t=(ll)t*x%mo;
return t;
}
int gcd(int a,int b){
return (b?gcd(b,a%b):a);
}
int C(int n,int m){
if (m<0||n<m) return 0;
return (ll)fac
*inv[m]%mo*inv[n-m]%mo;
}
int solve(int n,int m){
return (2*C(n-m-1,m-1)%mo+C(n-m-1,m))%mo;
}
int calc(int n,int m){
if (n<0){
if (m==0) return 1;else return 0;
}
if (m<0) return 0;
if (n==0){
if (m==0) return 1;else return 0;
}
if (n==m){
if (n==1) return 1;else return 0;
}
if (n-m-1<0) return 0;
int t=C(n-m-1,m-2);
t=(t+2*C(n-m-1,m-1)%mo)%mo;
t=(t+C(n-m-1,m))%mo;
return t;
}
int main(){
freopen("round.in","r",stdin);freopen("round.out","w",stdout);
scanf("%d%d",&n,&k);
if (n==1){
if (k==0) printf("1\n");else printf("0\n");
return 0;
}
if (n==2){
if (k==0||k==1) printf("1\n");else printf("0\n");
return 0;
}
if (n==4){
if (k==0||k==1||k==2) printf("1\n");else printf("0\n");
return 0;
}
fac[0]=1;
fo(i,1,n) fac[i]=(ll)fac[i-1]*i%mo;
inv
=quicksortmi(fac
,mo-2);
fd(i,n-1,0) inv[i]=(ll)inv[i+1]*(i+1)%mo;
ans=solve(n,k);
fo(i,1,n-1){
t=gcd(n,i);
if ((ll)k*t%n==0){
(ans+=solve(t,(ll)k*t/n))%=mo;
}
}
if (n%2==1){
if (k%2==1) ans=(ans+(ll)calc((n-1)/2-2,(k-1)/2)*n%mo)%mo;
else ans=(ans+(ll)calc((n-1)/2-1,k/2)*n%mo)%mo;
}
else{
if (k%2==1) ans=(ans+(ll)2*calc(n/2-2,(k-1)/2)%mo*(n/2)%mo)%mo;
else{
ans=(ans+(ll)calc(n/2-2,k/2)*(n/2)%mo)%mo;
ans=(ans+(ll)calc(n/2-3,k/2-1)*(n/2)%mo)%mo;
ans=(ans+(ll)calc(n/2-1,k/2)*(n/2)%mo)%mo;
}
}
ans=(ll)ans*quicksortmi(2*n,mo-2)%mo;
(ans+=mo)%=mo;
printf("%d\n",ans);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: