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); }
相关文章推荐
- jQuery滑动选取数值范围插件
- Java中List集合去除重复数据的方法
- 串口接收数据
- thinkphp session设置
- c语言中const 类型变量地址赋值给指针。
- linux下使用ack进行代码搜索
- MFC程序中创建文件夹(文件路径)
- Android获取屏幕宽高
- 使用MVP+RxAndroid+DroiBaaS打造云后台App—校园日记
- Firebase 远程配置 iOS 教程
- 基于 cuda aware 的多节点 多显卡程序编译
- iOS证书及ipa包重签名探究
- 裁切图片插件jcrop的简单使用(插件化)
- hdu1995 汉诺塔V
- webdriver结合tesseract-ocr处理简单验证码
- React Native ListView 资源收藏
- FTP命令列表------大写的命令如CWD_PASS
- ThinkPHP 模型方法 getField() 和 select() 使用技巧
- jQuery插件开发——全屏切换插件
- Mybatis学习--动态SQL