AGC005D - ~K Perm Counting

Solution

经典数排列个数题,写了个大麻烦容斥。

直接容斥,考虑求出fif_ifi​表示有iii个位置∣pi−i∣=k|p_i-i|=k∣pi​−i∣=k的方案数。一个位置iii满足∣pi−i∣=k|p_i-i|=k∣pi​−i∣=k,要么pi=i+kp_i=i+kpi​=i+k,要么pi=i−kp_i=i-kpi​=i−k,当前面的位置选择了pi=i+kp_i=i+kpi​=i+k时,后面的pi+2kp_{i+2k}pi+2k​就不能选择i+ki+ki+k了,前面可能对后面产生影响。

因此我们发现对于下标modkmod\;kmodk不同的位置之间一定没有影响,于是我们对modkmod\;kmodk余数分类,拉出nmodkn\mod knmodk条长为⌊nk⌋+1\lfloor\frac{n}{k}\rfloor+1⌊kn​⌋+1的链和k−nmodkk-n\mod kk−nmodk条长为⌊nk⌋\lfloor\frac{n}{k}\rfloor⌊kn​⌋的链,此时∣pi−i∣=k|p_i-i|=k∣pi​−i∣=k等价于选择了该点在链上的相邻点,把这些链的fff值用背包合并起来就是我们要求的fff。

于是我们要对每一种jjj,算出一条链上选取jjj个的方案数。令gi,j,kg_{i,j,k}gi,j,k​表示前iii点,选取jjj个相邻点,i−1,i,i+1{i-1,i,i+1}i−1,i,i+1的选取状态为kkk的方案数。

最后的答案要算上没选的点的任意选取的排列个数,即:
Ans=∑i=0n(−1)ifi(n−i)!Ans=\sum_{i=0}^n(-1)^if_i(n-i)!Ans=i=0∑n​(−1)ifi​(n−i)!

时间复杂度O(n2)O(n^2)O(n2),据说也有O(nlgn)O(nlgn)O(nlgn)的更麻烦做法。

Code

#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <queue>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cctype>
#include <string>
#include <cstring>
#include <ctime>
#include <cassert>
#include <string.h>
//#include <unordered_set>
//#include <unordered_map>
//#include <bits/stdc++.h>#define MP(A,B) make_pair(A,B)
#define PB(A) push_back(A)
#define SIZE(A) ((int)A.size())
#define LEN(A) ((int)A.length())
#define FOR(i,a,b) for(int i=(a);i<(b);++i)
#define fi first
#define se secondusing namespace std;template<typename T>inline bool upmin(T &x,T y) { return y<x?x=y,1:0; }
template<typename T>inline bool upmax(T &x,T y) { return x<y?x=y,1:0; }typedef long long ll;
typedef unsigned long long ull;
typedef long double lod;
typedef pair<int,int> PR;
typedef vector<int> VI;const lod eps=1e-11;
const lod pi=acos(-1);
const int oo=1<<30;
const ll loo=1ll<<62;
const int mods=924844033;
const int MAXN=2005;
const int INF=0x3f3f3f3f;//1061109567
/*--------------------------------------------------------------------*/
inline int read()
{int f=1,x=0; char c=getchar();while (c<'0'||c>'9') { if (c=='-') f=-1; c=getchar(); }while (c>='0'&&c<='9') { x=(x<<3)+(x<<1)+(c^48); c=getchar(); }return x*f;
}
int num=0,h[MAXN],g[MAXN][MAXN][8],f[MAXN],fac[MAXN],tmp[MAXN];
int upd(int x,int y) { return x+y>=mods?x+y-mods:x+y; }
void Merge(int q)
{for (int j=0;j<=q;j++) {h[j]=0;for (int t=0;t<4;t++) h[j]=upd(h[j],g[q][j][t]);}num+=q;for (int j=0;j<=num;j++) tmp[j]=0;for (int j=num;j>=0;j--)for (int k=0;k<=q;k++) if (j>=k) tmp[j]=upd(tmp[j],1ll*f[j-k]*h[k]%mods);for (int j=0;j<=num;j++) f[j]=tmp[j];
}
signed main()
{int n=read(),p=read(),q=n/p+1;fac[0]=1;for (int i=1;i<=n;i++) fac[i]=1ll*fac[i-1]*i%mods;g[1][0][0]=g[1][1][4]=1;for (int i=1;i<q;i++)for (int j=0;j<=i;j++){for (int k=0;k<8;k++) g[i+1][j][k>>1]=upd(g[i+1][j][k>>1],g[i][j][k]);for (int k=0;k<8;k++){if (!((k>>1)&1)) g[i+1][j+1][(k>>1)|1]=upd(g[i+1][j+1][(k>>1)|1],g[i][j][k]);if (!((k>>1)&4)) g[i+1][j+1][(k>>1)|4]=upd(g[i+1][j+1][(k>>1)|4],g[i][j][k]);}}f[0]=1;int r=n%p; for (int i=1;i<=r;i++) Merge(q);for (int i=1;i<=p-r;i++) Merge(q-1);int ans=0;for (int i=0;i<=n;i++) if (i&1) ans=upd(ans,mods-1ll*f[i]*fac[n-i]%mods);else ans=upd(ans,1ll*f[i]*fac[n-i]%mods);printf("%d\n",ans);return 0;
}

AGC005D - ~K Perm Counting(组合数学,背包,dp)相关推荐

  1. AGC005D ~K Perm Counting

    ~K Perm Counting 神仙题++ 转二分图+容斥比较好想 主要是最后的合并统计怎么做方便比较有趣 ptx大爷的博客 戳我 把二分图拆成链的想法很好 mark一下qwq 注意容斥的时候转lo ...

  2. 【LibreOJ】#6395. 「THUPC2018」城市地铁规划 / City 背包DP+Prufer序

    [题目]#6395. 「THUPC2018」城市地铁规划 / City [题意]给定n个点要求构造一棵树,每个点的价值是一个关于点度的k次多项式,系数均为给定的\(a_0,...a_k\),求最大价值 ...

  3. 【bzoj4007】[JLOI2015]战争调度 暴力+树形背包dp

    题目描述 给你一棵 $n$ 层的完全二叉树,每个节点可以染黑白两种颜色.对于每个叶子节点及其某个祖先节点,如果它们均为黑色则有一个贡献值,如果均为白色则有另一个贡献值.要求黑色的叶子节点数目不超过 $ ...

  4. HDU 1011 Starship Troopers 树形+背包dp

    http://acm.hdu.edu.cn/showproblem.php?pid=1011   题意:每个节点有两个值bug和brain,当清扫该节点的所有bug时就得到brain值,只有当父节点被 ...

  5. 【bzoj4753】[Jsoi2016]最佳团体 分数规划+树形背包dp

    题目描述 JSOI信息学代表队一共有N名候选人,这些候选人从1到N编号.方便起见,JYY的编号是0号.每个候选人都由一位编号比他小的候选人Ri推荐.如果Ri=0则说明这个候选人是JYY自己看上的.为了 ...

  6. 【bzoj5072】[Lydsy十月月赛]小A的树 树形背包dp

    题目描述 给出一棵n个点的树,每个点有黑白两种颜色.q次询问,每次询问给出x和y,问能否选出一个x个点的联通子图,使得其中黑点数目为y. 输入 第一行一个正整数 T 表示数据组数. 对于每一组数据,第 ...

  7. 【背包DP练习】洛谷 P5020货币系统 P1757通天之分组背包 P1064[NOIP2006 提高组]金明的预算方案 P5322 [BJOI2019]排兵布阵

    洛谷 P5020货币系统 https://www.luogu.com.cn/problem/P5020 思路是把货币从小到大排序,然后按顺序依次完全背包dp,每次dp检查i-1种面值的货币能不能凑出第 ...

  8. hdu 5234 Happy birthday 背包 dp

    Happy birthday Time Limit: 20 Sec  Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?p ...

  9. (背包dp) 背包N讲

    文章目录 前言 相关练习题 模板题 01背包 完全背包 多重背包 小数据范围 (可朴素暴力) 中等数据范围 (二进制优化) 大数据范围 (单调队列优化) 混合背包 二维费用背包 分组背包 有依赖的背包 ...

最新文章

  1. C++ 中的左值(Lvalues)和右值(Rvalues)
  2. 基于python的视频监控系统_Python远程视频监控程序的实例代码
  3. 学python必须知道的30个技巧
  4. 一位程序员工作10年总结的13个忠告
  5. 【精品计划 附录2】- 算法分析
  6. JVM证书制作步骤+耶鲁 CAS 配置
  7. MFC体系结构(3)
  8. 滴滴业务中台构建实践,首次曝光
  9. ISO27001风险评估实施流程(详细版)
  10. Excel技能培训之十四 统计函数count,countif,counta,countblank,large,small,average,max,min
  11. Andriod 实现可拖动列表
  12. 从零开始的LC刷题(56): Power of Two
  13. 2022 MegCup | 小模型盲降噪怎么比?资深炼丹师给你赛前指导!
  14. 表达式和语句的简单理解
  15. PE结构学习(4)_节的操作
  16. jmonkeyEngineSDK安装部署及IDEA集成JME3开发
  17. 达内cgb2111第三次月考 76分就够了
  18. RTX3080在Ubuntu 20.04复现yolact
  19. Altium designer中文化设置
  20. ps-色彩模式与图像色彩调整

热门文章

  1. 你的女神今日结婚了!!!你失恋了......
  2. 那些奇奇怪怪的男性用品......
  3. 数学到底有多难难难难?看完这个,瞬间觉得智商都提高了!
  4. 你为什么不爱发朋友圈了?
  5. 一定要多角度看事物 | 今日最佳
  6. 你的专业 VS 你妈口中你的专业
  7. 一位像素艺术家用39张动图,将大自然的唯美尽收眼底…
  8. sas数据导入终极汇总-之二
  9. 计算机PS英语词汇,操作计算机必读(必会)的53个英文单词共享
  10. 怎么部署_2020怎么部署新零售商城?