标签:暴力 sum type lib 通过 相同 char 记录 lock
给定 \(n\) 个数,\(x_i\) 的取值范围 \([a_i,b_i]\)。
求不同的 \(\sum\limits_{i=1}^{n}x_{i}^{2}\) 的种类数。
\(1\le n,a_i,b_i\le 100\)。
数据范围比较喜人,\(\sum x_i^2\) 的值域较小,考虑一波暴力。
开 n 个 vector,记录 \(1\sim i\) 能组成的所有数。
对于第 \(i+1\) 个数,枚举 \(1\sim i\) 能组成的所有数进行转移,可以写出下面的暴力代码。
\(n,a_i,b_i\) 同阶,复杂度是 \(O(n^4)\) 级别。
发现这个转移很像 01 背包的转移,加之值域较小。
考虑直接用 01 背包求能组成哪些数。
设 \(f_{i,j} = (0/1)\) 表示当前枚举到第 \(i\) 个数,能否通过 \(1\sim i\) ,组成 \(j\)。
有状态转移方程:
01 背包倒序枚举消去第一维,复杂度 \(O(n^2)\) 级别。
发现用个桶判定出现这里好傻逼啊,考虑用 bitset 进行维护。
转移与上述 01 背包的方法本质相同,直接右移或起来即可。
正解
//知识点:bitset
/*
By:Luckyblock
*/
#include <algorithm>
#include <cstdio>
#include <ctype.h>
#include <cstring>
#include <bitset>
#define ll long long
const int kMaxn = 110;
//=============================================================
int n;
std :: bitset <kMaxn * kMaxn * kMaxn> vis[kMaxn];
//=============================================================
inline int read() {
int f = 1, w = 0;
char ch = getchar();
for (; !isdigit(ch); ch = getchar())
if (ch == ‘-‘) f = -1;
for (; isdigit(ch); ch = getchar()) w = (w << 3) + (w << 1) + (ch ^ ‘0‘);
return f * w;
}
void GetMax(int &fir_, int sec_) {
if (sec_ > fir_) fir_ = sec_;
}
void GetMin(int &fir_, int sec_) {
if (sec_ < fir_) fir_ = sec_;
}
//=============================================================
int main() {
n = read();
vis[0][0] = true;
for (int i = 1; i <= n; ++ i) {
int a = read(), b = read();
for (int j = a; j <= b; ++ j) {
vis[i] |= (vis[i - 1] << (j * j));
}
}
printf("%d\n", vis[n].count());
return 0;
}
暴力
//傻逼暴力/cy
//判定出现这里好傻逼啊,改成bitset试试
#include <algorithm>
#include <cstdio>
#include <ctype.h>
#include <cstring>
#include <vector>
#define ll long long
const int kMaxn = 110;
//=============================================================
int n;
bool vis[kMaxn][kMaxn * kMaxn * kMaxn];
std :: vector <int> ans;
//=============================================================
inline int read() {
int f = 1, w = 0;
char ch = getchar();
for (; !isdigit(ch); ch = getchar())
if (ch == ‘-‘) f = -1;
for (; isdigit(ch); ch = getchar()) w = (w << 3) + (w << 1) + (ch ^ ‘0‘);
return f * w;
}
void GetMax(int &fir_, int sec_) {
if (sec_ > fir_) fir_ = sec_;
}
void GetMin(int &fir_, int sec_) {
if (sec_ < fir_) fir_ = sec_;
}
//=============================================================
int main() {
n = read();
ans.push_back(0);
for (int i = 1; i <= n; ++ i) {
int a = read(), b = read();
std :: vector <int> tmp;
for (int j = a; j <= b; ++ j) {
int x = j * j;
for (int k = 0, size = ans.size(); k < size; ++ k) {
int now = ans[k] + x;
if (! vis[i][ans[k] + x]) {
vis[i][ans[k] + x] = true;
tmp.push_back(ans[k] + x);
}
}
}
ans.clear();
for (int k = 0, size = tmp.size(); k < size; ++ k) {
ans.push_back(tmp[k]);
}
}
printf("%d\n", ans.size());
return 0;
}
标签:暴力 sum type lib 通过 相同 char 记录 lock
原文地址:https://www.cnblogs.com/luckyblock/p/13603957.html