想了很久觉得自己做法肯定T啊,就算是CF机子的3s时限,但我毕竟是 O ( C(15,7)*7!*log ) ....

果然在n=15的点T了...贱兮兮地特判了15过掉了,结果发现题解说就是打表...

(卒,享年16岁)

总之啊总之,要灵活啊

回归机房以后发现Div2的D都要想一个世纪了......不过感觉这题真的挺好的?

命不久矣,所以想最后写写题解吧。

题目大意:求满足  a+b=c( a,b,c均为长度为n的排列)的有序对{a,b}的对数

(说明:a,b,c均为0~(n-1)的排列  +运算为题中定义的+的等价修改  即ci=(ai+bi)mod n )

∆初步分析,有 2*n*(n-1)/2 = n*k + n*(n-1)/2 (k为整数) 则有 k=(n-1)/2 则n必须为奇数 否则答案为0

∆显然,{a,c}和{a,b}是一一对应的,所以我们不妨求{a,c}的有序对数(实际上这个转换并没有什么用处,只是我感觉爽....)

∆进一步化简,不妨将a固定为{0,1,2...n-1},则最终所求方案数* n! 即为答案。

∆考虑c需要满足的条件:

  (1)i-ci=j-cj(mod n) 对于任意 i!=j 均不成立

  (2)ci为0~n-1 且互不相同

(2)较容易解决,记录出现的数字即可。考虑如何满足(1)。想象你是在玩一个类似数独的游戏,在一个一个填数字,那么你只要保证:1.已经填上的数字彼此之间满足(1).(2)  2.新填入的第i+1个数字和前i个数字不重复、不冲突。

由此,我们可以像填数独一样,列出下一个格子不能取的值。那么我们就有一个大致思路,即状压,记录两维状态v1,v2(即由条件(1)、(2),下一位不能取的数字有哪些)。转移只需枚举下一位的可行数字x,在v1并入x,在v2并入x并循环右移1位( ci !=( val=cj-j+i )   ci+1 != (val+1=cj-j+i+1) ) 。

∆然鹅,这样复杂度很高(上界可达 O(n*22n) ?总之打表估计都GG),因此我们考虑进一步优化。

优化的本质就是探寻性质。我们发现,对于f[v1][v2]>0,v1和v2中的1个数一定相同,即在v2中并入数字时一定不会并入一个已经存在的位。可以用反证法证明,若并入ci对ci+1的影响时,该位已有cj对ci+1的影响,那么i、j两位就一定不符合(2)。

也就是说,v1,v2是可以「拆分」的。

∆「拆分」具体是什么意思呢?我们来模拟一下。

假设n=7,当前已经放了4个数:

v1=1100110

v2=1001011

现在我们挨个放入剩下的数字。例如:

v1=1120110

v2=0210111

v1=1123110

v2=2131110

v1=1123114

v2=1311142

将末状态和初状态做差,得到:

v1=0023004

v2=0300042

v1=0011001

v2=0100011

我们发现 对于初状态的{v1,v2} 差状态即为{1111111^v1, turn(1111111^v1,3) }

(turn(j,ct)表示将j循环右移ct位)

∆于是 我们就可以开心地折半搜索了!复杂度见第一行

(以下是打表代码,如果直接复制会在n=15的点TLE)

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3
 4 #define rep(i,l,r) for(int i=l;i<=r;++i)
 5 #define per(i,r,l) for(int i=r;i>=l;--i)
 6 #define mp make_pair
 7 #define fir first
 8 #define sec second
 9
10 typedef  long long ll;
11 typedef pair<int,int> pii;
12
13 const int p=1000000007,V=1e6+3;
14
15 int n,full,semi,turn[V];
16 map<pii,int>f[2];
17 map<pii,int>::iterator it;
18
19 int rev(int j){//j循环右移1位
20     int ans=0;
21     if(j>=semi){
22         ans=1;
23         j-=semi;
24     }
25
26     return ans|(j<<1);
27 }
28
29 int main(){
30     scanf("%d",&n);
31
32     if(n==1){
33         printf("1");
34         return 0;
35     }
36
37     if(n%2==0){
38         printf("0");
39         return 0;
40     }
41
42     full=(1<<n)-1;
43     semi=(1<<(n-1));
44
45
46     int u=(n>>1);
47
48     f[0][mp(0,0)]=1;
49
50     //多出的一维[0/1]是在愚蠢地省空间...
51     bool oi=0;
52     rep(o,0,u){
53         f[!oi].clear();
54
55         for(it=f[oi].begin();it!=f[oi].end();++it){
56             pii P=it->fir;int val=it->sec;
57             int L=P.fir,R=P.sec;
58
59             int j=(L|R);
60             if(j==full) continue;
61
62             rep(i,0,n-1) if( ( (1<<i)&L ) ==0  && ( (1<<i)&R ) ==0  )
63                 (f[!oi][mp( ( L|(1<<i) ) , rev( R|(1<<i) ) )]+=val)%=p;
64
65         }
66
67         oi=!oi;
68     }
69
70     int pre=(1<<(u+1))-1,suf=full^pre;
71     rep(i,1,full) turn[i]=((i&pre)<<u)|((i&suf)>>(u+1));
72     //turn[i]即i循环右移(n/2)位
73
74     ll ans=0;
75     for(it=f[oi].begin();it!=f[oi].end();++it){
76         pii P=it->fir;ll val=it->sec;
77         int L=P.fir,R=P.sec;
78
79         (ans+=val*f[!oi][mp(full^L,turn[full^R])]%p)%=p;
80     }
81
82     rep(i,1,n) (ans*=i)%=p;
83
84     printf("%lld",ans);
85
86     return 0;
87 }

转载于:https://www.cnblogs.com/BLeaves/p/10760465.html

CF285D.Permutation Sum相关推荐

  1. cf 1512 E. Permutation by Sum

    cf 1512 E. Permutation by Sum 题意: 我们定义排列的概念为:从1到n的整数组成的序列,每个数字只出现一次 现在给你n,l,r,s,让你构造一个长度为n的排列,使得其中的第 ...

  2. 【C++】C++11 STL算法(七):排列操作(Permutation operations)、数值操作(Numeric operations)

    排列操作(Permutation operations) 一.is_permutation 1.原型: template< class ForwardIt1, class ForwardIt2 ...

  3. 2017 Multi-University Training Contest - Team 3 Kanade's sum hd6058

    地址:http://acm.split.hdu.edu.cn/showproblem.php?pid=6058 题目: Kanade's sum Time Limit: 4000/2000 MS (J ...

  4. hdu 4676 Sum Of Gcd 莫队+phi反演

    Sum Of Gcd 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=4676 Description Given you a sequence of ...

  5. CodeForces - 1553E Permutation Shift(暴力+置换群求环)

    题目链接:点击查看 题目大意:假设初始时的数组为 [1,2,3,...,n][1,2,3,...,n][1,2,3,...,n],同时 kkk 为偏移量,则原数组会循环右移 kkk 个单位,假设 k= ...

  6. Permutation Partitions CodeForces - 1326C(组合数学+思维)

    You are given a permutation p1,p2,-,pn of integers from 1 to n and an integer k, such that 1≤k≤n. A ...

  7. Restoring Permutation CodeForces - 1315C(思维)

    You are given a sequence b1,b2,-,bn. Find the lexicographically minimal permutation a1,a2,-,a2n such ...

  8. I - Interesting Permutation Gym - 102394I(排列组合)

    题意: 纯数题 1≤i≤n, fi=max{a1,a2,-,ai}; 1≤i≤n, gi=min{a1,a2,-,ai}; 1≤i≤n, hi=fi−gi. 数列a是一个排列,问多少种排列方式满足h数 ...

  9. CF1208D Restore Permutation

    CF1208D Restore Permutation 题意: 现在有一个从1到n的一个全排列,但是你不知道这个排列到底是什么,但是你有一个sum[i],其中sum[i]表示∑j=1i−1(aj< ...

最新文章

  1. pandas使用extract函数根据正则表达式从dataframe指定数据列的字符串中抽取出数字(设置expand=false之后返回的为series)、将series转化为dataframe
  2. ​AAAI 2022 | 基于强化学习的视频弹幕攻击
  3. java 基本数据类型及自己主动类型提升
  4. Opencv——DFT变换(实现两个Mat的卷积以及显示Mat的频域图像)
  5. 文本生成系列之预训练模型
  6. 国科大模式识别与机器学习课程整理
  7. linux识别riser卡,一种应用在GPU服务器中可灵活配置的Riser卡的制作方法
  8. wmf和emf格式的图片有什么区别? JPG图片如何转换WMF文件?
  9. 读书会 | 第一季读书会《蛤蟆先生去看心理医生》完美收官啦
  10. IT互联网行业猎头的年终总结:结束后开始
  11. 线程安全问题和解决方法
  12. maven安装使用手册之-----------------------maven介绍及安装部署
  13. WhatsApp的下载与更新
  14. 展望未来~走向计算机之路
  15. Linux:VNC桌面锁屏问题处理
  16. 大数据开发好找工作么?还能入行么?
  17. 文献阅读:Scaling Instruction-Finetuned Language Models
  18. 2022-01-08
  19. Android studio 使用androidX后应用启动log中报Didn‘t find class “android.view.View$OnUnhandledKeyEventListener“
  20. UI自动化测试如何去实现无头模式必踩的坑

热门文章

  1. 转-登录功能通用测试用例设计
  2. Constructor vs Object
  3. 删除同目录下面txt文件(利用os,fnmacth模块)
  4. Linux NFS存储服务部署
  5. 清北学堂模拟赛d6t4 数组异或
  6. ubuntu-ln命令
  7. 第二届360杯全国大学生信息安全技术大赛部分解题思路(加密解密题)
  8. 修改看板视图默认显示个数
  9. CSS3新增了哪些特性
  10. 豆腐怎么做小朋友才喜欢吃?