[34](CSP 集训)CSP-S 联训模拟 1
A 几何
重复若干次 -> 不能重叠,因此考虑直接暴力 DP
设
转移非常好写,枚举
复杂度是
endl 改 \n,代码生下来常数就小的直接过了
否则的话考虑直接 bitset(能 bitset 是因为这题的 dp 数组全是 bool,转移也全是或运算),预处理出
还过不了就是孩子代码一生下来常数就大
解决方案:手写一个用 ull 压
#include<bits/stdc++.h>
using namespace std;
#pragma GCC optimize(3)
#define endl '\n'
int cases;
string s,x,y;
bool f[2][51][51];
// 0:x 1:y
int main(){
ios::sync_with_stdio(false);
freopen("geometry.in","r",stdin);
freopen("geometry.out","w",stdout);
cin>>cases;
while(cases--){
cin>>s>>x>>y;
f[0][0][0]=1;
for(int i=1;i<=(int)s.length();++i){
for(int j=0;j<=(int)x.length();++j){
for(int k=0;k<=(int)y.length();++k){
f[i&1][j][k]&=0;
}
}
for(int j=0;j<=(int)x.length();++j){
for(int k=0;k<=(int)y.length();++k){
if(j!=0 and s[i-1]==x[j-1]){
f[i&1][j!=(int)x.length()?j:0][k!=(int)y.length()?k:0]|=f[(i-1)&1][j-1][k!=(int)y.length()?k:0];
}
if(k!=0 and s[i-1]==y[k-1]){
f[i&1][j!=(int)x.length()?j:0][k!=(int)y.length()?k:0]|=f[(i-1)&1][j!=(int)x.length()?j:0][k-1];
}
}
}
}
if(f[((int)s.length())&1][0][0]==true){
cout<<"Yes"<<endl;
}
else{
cout<<"No"<<endl;
}
}
}
/*
abaaabbaab
1112112122
[1 0]
[2 0]
[3 0]
bbaabaabaaabaabaab
221111111121111111
[2,0]
bba
aab
*/
B
我说我的爆搜为什么不对,拉下来对拍拍出一组十字架图
因为我一开始觉得删边等于删点,所以我就每次路过把点删了,但是事实上不是这样,所以这题
因为题目里这么走,相当于走了一个欧拉路,然而欧拉路是要求最多两个节点是奇点,因此考虑转移问题为使原图变为欧拉路
设
首先,操作
假如我们把
接下来看
如果我们执行
如果两个点全是偶点,本来能自己过去,非要瞬移到另一边,现在过不去了,还要再瞬移回来,所以会让
否则,实际上瞬移一下没啥变化,
统计答案的时候,原图可以是欧拉回路,或者可以存在两个奇点(此时需要一次瞬移),注意这个奇点不一定非要有一个在根节点上
#include<bits/stdc++.h>
using namespace std;
#define int long long
int n,a,b;
vector<int>e[500001];
const int inf=LLONG_MAX/10;
int f[500001][2][2],g[2][2];
void dfs(int now,int last){
f[now][0][0]=0;
f[now][0][1]=inf;
f[now][1][0]=inf;
f[now][1][1]=inf;
for(int i:e[now]){
if(i!=last){
dfs(i,now);
for(int j=0;j<=1;++j){
for(int k=0;k<=1;++k){
g[j][k]=f[now][j][k];
f[now][j][k]=inf;
}
}
for(int j=0;j<=1;++j){
for(int k=0;k<=1;++k){
for(int l=0;l<=1;++l){
for(int m=0;m<=1;++m){
f[now][j][k|l|m]=min(f[now][j][k|l|m],g[j][k]+f[i][l][m]+a);
int cost=0;
if(!j and !l) cost=b;
else if(j and l) cost=-b;
f[now][1-j][k|(1-l)|m]=min(f[now][1-j][k|(1-l)|m],g[j][k]+f[i][l][m]+cost);
}
}
}
}
}
}
}
signed main(){
freopen("analyse.in","r",stdin);
freopen("analyse.out","w",stdout);
cin>>n>>a>>b;
for(int i=1;i<=n-1;++i){
int x,y;cin>>x>>y;
e[x].push_back(y);
e[y].push_back(x);
}
dfs(1,0);
cout<<min({f[1][0][0],f[1][1][1]-b,f[1][0][1]-b});
}
D 组合
神秘题,但是我觉得这个思路还是很好的
首先因为不会对你的询问返回答案,也就意味着没办法用类似二分的方法求解,否则会被卡成完全二叉树
题目让我们构造
只考虑其中的三组二进制数,发现这三组有贡献的条件是两两位或结果不同,证明:设
然后就到了神秘的地方,怎么构造这
STD 的做法是枚举
这个
好在结论题比较好改
ADD: 其实这个 STD 挺好写的,__builtin_popcount() 是用来数二进制数里
STD
#include<bits/stdc++.h>
using namespace std;
int N = 20;
int a[1015];
bitset<1073741824> bk;
int main() {
int cur = 0;
vector<int> vec;
for (int i = 0; i < (1 << N); i++) {
if (__builtin_popcount(i) == 8)
vec.push_back(i);
}
for (int i = 0; i < (1 << N); i++) {
if (__builtin_popcount(i) == 9)
vec.push_back(i);
}
for (int i = 1; i <= 1010; i++) {
bool fl2 = 0;
for (auto t : vec) {
a[i] = t;
bool fl = 0;
for (int j = 1; j <= i; j++) {
if (bk[a[i] | a[j]] || (i != j && i <= 996 && __builtin_popcount(a[i] | a[j]) < 11)) {
fl = 1;
for (int k = 1; k < j; k++)
bk[a[i] | a[k]] = 0;
break;
}
bk[a[i] | a[j]] = 1;
}
if (fl)
continue;
fl2 = 1;
break;
}
if (!fl2) {
N++;
vec.clear();
for (int j = 0; j < (1 << N); j++) {
if (__builtin_popcount(j) == 8)
vec.push_back(j);
}
if (N >= 24) {
for (int j = 0; j < (1 << N); j++) {
if (__builtin_popcount(j) == 9)
vec.push_back(j);
}
}
if (N == 26) {
for (int j = 0; j < (1 << N); j++) {
if (__builtin_popcount(j) != 8 && __builtin_popcount(j) != 9)
vec.push_back(j);
}
}
i--;
continue;
}
cout << i << ' ' << N << endl;
if (N > 26) {
cur = i - 1;
break;
}
}
freopen("output.txt", "w", stdout);
for (int i = 1; i <= 1000; i++)
cout << a[i] << ',';
cout << endl;
return 0;
}
#include<bits/stdc++.h>
using namespace std;
int a[]; //自己去跑 STD
string to_binary(int x){
string ans;
while(x){
if(x&1) ans.push_back('1');
else ans.push_back('0');
x>>=1;
}
// cout<<"::"<<ans<<endl;
while(ans.size()<26) ans.push_back('0');
reverse(ans.begin(),ans.end());
return ans;
}
vector<string>ans(27);
int main(){
ofstream cth("combination.out");
for(int i=0;i<=999;++i){
string as=to_binary(a[i]);
// cout<<as<<endl;
for(int j=0;j<=25;++j){
ans[j].push_back(as[j]);
}
}
cth<<26<<endl;
for(int i=0;i<=25;++i){
cth<<ans[i]<<endl;
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库