あいさか たいがblogAisaka_Taiga的博客
//https://img2018.cnblogs.com/blog/1646268/201908/1646268-20190806114008215-138720377.jpg

NOIP 2021 数列

NOIP 2021 数列

暴力#

下标看起来真的乱,30min 打完暴力:

Copy
/* * @Author: Aisaka_Taiga * @Date: 2023-10-27 15:32:25 * @LastEditTime: 2023-10-27 16:08:12 * @LastEditors: Aisaka_Taiga * @FilePath: \Desktop\P7961.cpp * The heart is higher than the sky, and life is thinner than paper. */ #include <bits/stdc++.h> #define int long long #define P 998244353 #define N 1000100 using namespace std; inline int read() { int x = 0, f = 1; char c = getchar(); while(c < '0' || c > '9'){if(c == '-') f = -1; c = getchar();} while(c <= '9' && c >= '0') x = (x << 1) + (x << 3) + (c ^ 48), c = getchar(); return x * f; } int n, m, k, a[N], b[N], ans; inline int ksm(int x, int y) { int res = 1; while(y) { if(y & 1) res *= x; x *= x, y >>= 1; } return res; } inline void check(int xx) { int cnt = 0, res = 1; while(xx) { if(xx & 1) cnt ++; xx >>= 1; } // for(int i = 1; i <= n; i ++) // cout << b[i] << " "; // cout << endl; if(cnt > k) return ; for(int i = 1; i <= n; i ++) res = (res * a[b[i]]) % P; ans = (ans + res) % P; return ; } inline void dfs(int sum, int cnt) { if(cnt == n + 1) return check(sum), void(); for(int i = 0; i <= m; i ++) { b[cnt] = i; dfs(sum + ksm(2, i), cnt + 1); // b[cnt] = 0; } return ; } signed main() { n = read(), m = read(), k = read(); for(int i = 0; i <= m; i ++) a[i] = read(); dfs(0, 1); cout << ans << endl; return 0; } /* 8 9 1 499488183 118995914 332316574 399234563 246850128 338768262 489466833 673193710 723933572 12759125 */

由于太过暴力所以导致他在 O2 以及快速幂的加持下才拿到了 5pts。

正解#

考虑搜索最终每一位上的数选多少个,然后根据组合数计算价值和。

那么我们直接搜肯定过不了,要记忆化,设 f[x][y][a][b] 表示当前枚举到 x,填了 y 个数,处理完的位上的 1 的个数为 a,前面进位对当前位的贡献为 b

接下来处理答案的计算以及下一个搜索的状态。

设当前位选了 x 个,那么这次搜索回来的值要乘上 a[i]x×Cnyx, 前面那部分就是取 x 个对答案的贡献,后面就是从剩下的 xy 个位置里选 x 个填上当前枚举的数的方案数。

而对于 a 的计算,只考虑当前位是不是为 1 即可,也就是下一层搜索的 a 的状态更新为 (a+b)mod2,加 b 是因为前面的进位会影响这里是不是 1;对于 b,直接除以 2 即可。

那么最后得出转移方程:

f[x][y][a][b]=i=0nyf[x+1][y+i][(a+b)&1][a+b2]×vxi×Cnyi

Copy
/* * @Author: Aisaka_Taiga * @Date: 2023-10-27 15:32:25 * @LastEditTime: 2023-10-27 17:11:25 * @LastEditors: Aisaka_Taiga * @FilePath: \Desktop\P7961.cpp * The heart is higher than the sky, and life is thinner than paper. */ #include <bits/stdc++.h> #define int long long #define P 998244353 #define N 110 #define M 35 using namespace std; inline int read() { int x = 0, f = 1; char c = getchar(); while(c < '0' || c > '9'){if(c == '-') f = -1; c = getchar();} while(c <= '9' && c >= '0') x = (x << 1) + (x << 3) + (c ^ 48), c = getchar(); return x * f; } int n, m, k, ans, a[N], c[M][M], p[N][M], f[N][M][M][M]; inline int popcnt(int x)//??计算一个数转成二进制后一的个数 { int res = 0; while(x) { if(x & 1) res ++; x >>= 1; } return res; } inline int dfs(int x, int y, int a, int b)//x是当前a的值,y是当前选了的个数 {//a是当前已经处理完的位上的1的个数,b是进位后当前位相当于有多少个2^x if(y >= n) return a + popcnt(b) <= k;//a是前几个位的1个数,popcnt b是进位产生的1的个数 if(x > m) return 0;//越界了,没有合法方案 if(f[x][y][a][b] != -1) return f[x][y][a][b];//记忆化 int res = 0;//当前状态下的答案 for(int i = 0; i <= n - y; i ++)//一个不选~最多能选的个数 res = (res + dfs(x + 1, y + i, a + ((b + i) & 1), ((b + i) >> 1)) * p[x][i] % P * c[n - y][i] % P) % P; return f[x][y][a][b] = res;//记忆化 } signed main() { memset(f, -1, sizeof f); n = read(), m = read(), k = read(); for(int i = 0; i <= m; i ++) a[i] = read(); for(int i = 1; i <= n; i ++) { c[i][0] = c[i][i] = 1; for(int j = 1; j < i; j ++) c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % P; }//预处理组合数 for(int i = 0; i <= m; i ++) { p[i][0] = 1; for(int j = 1; j <= n; j ++) p[i][j] = p[i][j - 1] * a[i] % P; }//预处理a[i]^j ans = dfs(0, 0, 0, 0); cout << ans << endl; return 0; } /* 8 9 1 499488183 118995914 332316574 399234563 246850128 338768262 489466833 673193710 723933572 12759125 5 1 1 2 1 */
posted @   北烛青澜  阅读(7)  评论(0编辑  收藏  举报
编辑推荐:
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示
目录