CodeForces 1152F1 Neko Rules the Catniverse (Small Version)

题目链接:http://codeforces.com/problemset/problem/1152/F1

题目大意

  有 n 个星球,给定限制 m,从 x 星球走到 y 星球的条件是,$1 \leq y \leq x + m$,且 y 不能被访问过。
  求游玩其中 k 个星球有多少种不同的方案?

分析

  一开始我的想法是二维 dp,dp[i][j] 表示前 i 个星球,访问其中 j 个,一共的方案种数,然后在遍历到第 i + 1 个星球的时候,很明显有访问和不访问两种操作,不访问好算,直接赋值即可,而访问就难算了,因为 dp[i + 1][j + 1] 与编号在 [i - m + 1, i] 区间内的星球访问状况是相关的,以 m == 4 为例,假设后四个星球的访问状态为 “1010”(1代表访问了,0代表没访问),那么第 i + 1 号星球,可以在第 i - 3 号星球之后被访问,也可以在第 i - 1 号星球之后被访问,也可以第一个被访问。也就是说,对于前 i 个星球,访问其中 j 个的每一种可行方案,都可以拆分成把第 i + 1 号星球插到第 i - 3 号后,把第 i + 1 号星球插到第 i - 1 号后,把第 i + 1 号星球插到第一个一共三种方案。因此 dp[i + 1][j + 1] = 3 * dp[i][j](后4个星球的访问状态为“1010”)。

  通过上面的分析,可以得知 dp 数组应该是三维的,第三维就是后m个星球的访问状态。此题为状压dp。

  dp[i][j][sta] 表示前 i 个星球,访问其中 j 个,后m个星球的访问状态为 sta 时一共的方案种数。

  当遍历到第 i + 1 号星球时,状态转移方程为:

  1. 不访问:dp[i + 1][j][newsta] += dp[i][j][sta],newsta = (sta << 1) % (1 << m)。
  2. 访问:dp[i + 1][j + 1][newsta] += dp[i][j][sta] * (1 + 后m个星球被访问过的星球个数),newsta = ((sta << 1) % (1 << m)) | 1。

  初始状态为 dp[0][0][0] = 1,dp[0][j][sta] = 0。

  PS:newsta 可能对应多种不同的访问星球集合,所以要用 += 而不能用 =。

代码如下

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3
  4 #define INIT() ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
  5 #define Rep(i,n) for (int i = 0; i < (n); ++i)
  6 #define For(i,s,t) for (int i = (s); i <= (t); ++i)
  7 #define rFor(i,t,s) for (int i = (t); i >= (s); --i)
  8 #define ForLL(i, s, t) for (LL i = LL(s); i <= LL(t); ++i)
  9 #define rForLL(i, t, s) for (LL i = LL(t); i >= LL(s); --i)
 10 #define foreach(i,c) for (__typeof(c.begin()) i = c.begin(); i != c.end(); ++i)
 11 #define rforeach(i,c) for (__typeof(c.rbegin()) i = c.rbegin(); i != c.rend(); ++i)
 12
 13 #define pr(x) cout << #x << " = " << x << "  "
 14 #define prln(x) cout << #x << " = " << x << endl
 15
 16 #define LOWBIT(x) ((x)&(-x))
 17
 18 #define ALL(x) x.begin(),x.end()
 19 #define INS(x) inserter(x,x.begin())
 20
 21 #define ms0(a) memset(a,0,sizeof(a))
 22 #define msI(a) memset(a,inf,sizeof(a))
 23 #define msM(a) memset(a,-1,sizeof(a))
 24
 25 #define MP make_pair
 26 #define PB push_back
 27 #define ft first
 28 #define sd second
 29
 30 template<typename T1, typename T2>
 31 istream &operator>>(istream &in, pair<T1, T2> &p) {
 32     in >> p.first >> p.second;
 33     return in;
 34 }
 35
 36 template<typename T>
 37 istream &operator>>(istream &in, vector<T> &v) {
 38     for (auto &x: v)
 39         in >> x;
 40     return in;
 41 }
 42
 43 template<typename T1, typename T2>
 44 ostream &operator<<(ostream &out, const std::pair<T1, T2> &p) {
 45     out << "[" << p.first << ", " << p.second << "]" << "\n";
 46     return out;
 47 }
 48
 49 inline int gc(){
 50     static const int BUF = 1e7;
 51     static char buf[BUF], *bg = buf + BUF, *ed = bg;
 52
 53     if(bg == ed) fread(bg = buf, 1, BUF, stdin);
 54     return *bg++;
 55 }
 56
 57 inline int ri(){
 58     int x = 0, f = 1, c = gc();
 59     for(; c<48||c>57; f = c==‘-‘?-1:f, c=gc());
 60     for(; c>47&&c<58; x = x*10 + c - 48, c=gc());
 61     return x*f;
 62 }
 63
 64 typedef long long LL;
 65 typedef unsigned long long uLL;
 66 typedef pair< double, double > PDD;
 67 typedef pair< int, int > PII;
 68 typedef pair< string, int > PSI;
 69 typedef set< int > SI;
 70 typedef vector< int > VI;
 71 typedef map< int, int > MII;
 72 typedef pair< LL, LL > PLL;
 73 typedef vector< LL > VL;
 74 typedef vector< VL > VVL;
 75 const double EPS = 1e-10;
 76 const LL inf = 0x7fffffff;
 77 const LL infLL = 0x7fffffffffffffffLL;
 78 const LL mod = 1e9 + 7;
 79 const int maxN = 1e5 + 7;
 80 const LL ONE = 1;
 81 const LL evenBits = 0xaaaaaaaaaaaaaaaa;
 82 const LL oddBits = 0x5555555555555555;
 83
 84 void add_mod(LL &a, LL b) {
 85     a = (a + b) % mod;
 86 }
 87
 88 int n, k, m;
 89 // dp[i][j][k] 表示在前 i 个星球中,选 j 个,第 i-m-1 ~ i 的选取状态的二进制表示为 k 时的方案数
 90 LL dp[maxN][13][16];
 91 LL ans;
 92
 93 int main(){
 94     INIT();
 95     cin >> n >> k >> m;
 96     int maxSta = 1 << m;
 97     dp[0][0][0] = 1;
 98
 99     Rep(i, n) {
100         Rep(j, k + 1) {
101             Rep(sta, maxSta) {
102                 int newsta = (sta << 1) % maxSta;
103                 // 不选 i + 1 个星球
104                 add_mod(dp[i + 1][j][newsta], dp[i][j][sta]);
105                 // 选 i + 1 个星球
106                 if (j < k) {
107                     LL insertWays = __builtin_popcount(sta) + 1;
108                     add_mod(dp[i + 1][j + 1][newsta | 1], insertWays * dp[i][j][sta]);
109                 }
110             }
111         }
112     }
113
114     Rep(sta, maxSta) add_mod(ans, dp[n][k][sta]);
115     cout << ans << endl;
116     return 0;
117 }

原文地址:https://www.cnblogs.com/zaq19970105/p/10886820.html

时间: 2024-08-30 17:36:38

CodeForces 1152F1 Neko Rules the Catniverse (Small Version)的相关文章

CodeForces 1152F2 Neko Rules the Catniverse (Large Version)

题目链接:http://codeforces.com/problemset/problem/1152/F2 题目大意 见http://codeforces.com/problemset/problem/1152/F1,此题 n 最大能到 109. 分析 在 F1 的基础上, 代码如下 时间复杂度:$O(\log n*(k*2^m)^3)$ 原文地址:https://www.cnblogs.com/zaq19970105/p/10886953.html

CodeForces 1292A NEKO&#39;s Maze Game(思维)

1 #include <stdio.h> 2 #include <string.h> 3 #include <iostream> 4 #include <string> 5 #include <math.h> 6 #include <algorithm> 7 #include <vector> 8 #include <stack> 9 #include <queue> 10 #include <

Codeforces . C.Neko does Maths

题目描述: C. Neko does Maths time limit per test 1 second memory limit per test 256 megabytes input standard input output standard output Neko loves divisors. During the latest number theory lesson, he got an interesting exercise from his math teacher. N

Codeforces 1152E Neko and Flashback 欧拉路径

Neko and Flashback 把a[ i ] - b[ i ] 看成边, 就是求一遍欧拉路径就好了. 注意图不连通的情况.. #include<bits/stdc++.h> #define fi first #define se second #define mk make_pair #define PII pair<int, int> using namespace std; const int N = (int)2e5 + 7; int n, a[N], b[N], d

Codeforces Round #535 E2-Array and Segments (Hard version)

题意: 给你一个数列和一些区间,让你选择一些区间(选择的区间中的数都减一), 求最后最大值与最小值的差值最大,并输出选择的区间 思路: 在n=300的时候,我们是枚举每个数作为最小值,应用所有覆盖它的区间,并且没 次都更行差值的最大值. 但是这里的n=1e5,所以我们不能用O(n*n*m),但是我们看到这里的m=300 所以可以从m入手,枚举区间,就是记录每个区间的两个端点,利用差分的思想, 来枚举更新最大值 这里说一下为什么枚举最小值,因为如果最大值也在这个区间则抵消,如果没在则 更好 #in

Codeforces 1249 D2. Too Many Segments (hard version)

传送门 贪心 对于第一个不合法的位置,我们显然要通过删除几个覆盖了它的区间来使这个位置合法 显然删右端点更靠右的区间是更优的,所以就考虑优先删右端点靠右的,然后再考虑下一个不合法位置 用一个 $set$ 维护一下右端点和区间编号即可 #include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> #include<vector

Codeforces 1108E2 Array and Segments (Hard version) 差分, 暴力

Codeforces 1108E2 E2. Array and Segments (Hard version) Description: The only difference between easy and hard versions is a number of elements in the array. You are given an array \(a\) consisting of \(n\) integers. The value of the \(i\)-th element

可编译易用的模块化nf-HiPAC移植成功

由于早在上周三对这个周末就有了别的安排,要折腾空气压缩机,突然接到通知又要陪老婆去考试,幸亏周四靠晚上的时间完成了nf-HiPAC的移植工作. 模块化nf-HiPAC的工作只能排在晚上完成,周四晚上折腾到12点终于算是完成了.效果也还不错,最初的tar包放到了下载频道"模块化的nf- HiPAC",也会有另外的人放在github上,下载频道的主要是为了使用,而github上的主要是为了更新,这主要鉴于nf-hipac在还有很多 TODO的情况下就停止了更新,这些TODO在其网页http

【IPv6总结】

IPV6的优势 1.更大地址空间,IPV6采用了128bit的地址长度,可以提供2^128个地址. 2.IPV6包头长度为固定40个字节,IPV4是40-60个字节:这样容易实现硬件式转发,提高转发效率 3.IPV6包头比IPV4包头简化,取消了网络层的校验工作,提高了网络层效率 4.引入灵活的扩展头,使得IPV6的协议扩展更加灵活,但是不是所有的路由器都需要处理IPV6的扩展头,这样中间路由器的转发提高了效率. 5.IPV6地址分配严格按照层次区域划分,使得骨干区域的IPV6路由能最大化的汇总