牛客2021年七夕节比赛大部分题解(因数枚举模板线段树dp……)
Posted hans774882968
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了牛客2021年七夕节比赛大部分题解(因数枚举模板线段树dp……)相关的知识,希望对你有一定的参考价值。
偶然刷到了,就做了一下。F是防AK,不会,ACDE水,略。
比较有参考价值的是I题,dp。
B
一开始想的是状压枚举素数集合,但是各素因子的幂不一定要统一。于是改成了直接dfs枚举所有素数的所有幂次,并逐一判定。
写完了一发AC了以后才发现,枚举所有素数的所有幂次也就是枚举所有因数,23333我是sb。不过这个枚举方法肯定比根号枚举要快一点。
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
#define rep(i,a,b) for(int i = (a);i <= (b);++i)
#define re_(i,a,b) for(int i = (a);i < (b);++i)
#define dwn(i,a,b) for(int i = (a);i >= (b);--i)
const int N = 32000 + 5;
int n;bool vis[N];vector<int> primes;
void dbg()puts("");
template<typename T, typename... R>void dbg(const T &f, const R &... r)
cout << f << " ";
dbg(r...);
template<typename Type>inline void read(Type &xx)
Type f = 1;char ch;xx = 0;
for(ch = getchar();ch < '0' || ch > '9';ch = getchar()) if(ch == '-') f = -1;
for(;ch >= '0' && ch <= '9';ch = getchar()) xx = xx * 10 + ch - '0';
xx *= f;
void read()
template<typename T,typename ...R>void read(T &x,R &...r)
read(x);
read(r...);
void init_p(int m)
vis[1] = true;
rep(i,2,m)
if(!vis[i]) primes.push_back(i);
for(int p: primes)
if(i > m / p) break;
vis[i * p] = true;
if(i % p == 0) break;
void dfs(vector<vector<int> > &vec,int &ans,int dep = 0,int mul = 1)
if(dep >= vec.size())
if(mul == 1) return;
int x = n;while(x % mul == 0) x /= mul;
if(x < mul) ans = min(ans,mul);
return;
int p = vec[dep][0];
for(int cur = 1;;cur *= p)
dfs(vec,ans,dep+1,mul*cur);
if(cur == vec[dep][1]) break;
int solve()
int x = n;
vector<vector<int> > vec;
for(int p: primes)
if(p > x/p) break;
int pw = 1;
while(x % p == 0)
x /= p;
pw *= p;
if(pw > 1) vec.push_back(p,pw);
if(x > 1) vec.push_back(x,x);
int ans = n;
dfs(vec,ans);
return ans;
int main(int argc, char** argv)
init_p(N-5);
int T;read(T);
while(T--)
read(n);
printf("%d\\n",solve());
return 0;
G
或运算有如下单调性:两个集合是子集关系,则子集的or值小于等于超集的or值。所以这题相当于询问区间或,以及区间赋值。套线段树模板。
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
#define rep(i,a,b) for(int i = (a);i <= (b);++i)
#define re_(i,a,b) for(int i = (a);i < (b);++i)
#define dwn(i,a,b) for(int i = (a);i >= (b);--i)
#define ls(x) ((x) << 1)
#define rs(x) ((x) << 1 | 1)
const int N = 1e6 + 5;
int n,m,a[N];
void dbg()puts("");
template<typename T, typename... R>void dbg(const T &f, const R &... r)
cout << f << " ";
dbg(r...);
template<typename Type>inline void read(Type &xx)
Type f = 1;char ch;xx = 0;
for(ch = getchar();ch < '0' || ch > '9';ch = getchar()) if(ch == '-') f = -1;
for(;ch >= '0' && ch <= '9';ch = getchar()) xx = xx * 10 + ch - '0';
xx *= f;
void read()
template<typename T,typename ...R>void read(T &x,R &...r)
read(x);
read(r...);
struct Nodeint sum,tg;nd[N<<2];
void pushup(int x)nd[x].sum = nd[ls(x)].sum | nd[rs(x)].sum;
void pushdown(int x)
int tg = nd[x].tg;
if(!tg) return;
nd[ls(x)].tg = nd[rs(x)].tg = nd[ls(x)].sum = nd[rs(x)].sum = tg;
nd[x].tg = 0;
void build(int l,int r,int x)
if(l == r)
nd[x] = a[l],0;return;
int mid = (l+r)>>1;
build(l,mid,ls(x));
build(mid+1,r,rs(x));
pushup(x);
void mdy(int ql,int qr,int v,int l = 1,int r = n,int x = 1)
if(ql <= l && r <= qr)
nd[x] = v,v;return;
pushdown(x);
int mid = (l+r)>>1;
if(ql <= mid) mdy(ql,qr,v,l,mid,ls(x));
if(qr > mid) mdy(ql,qr,v,mid+1,r,rs(x));
pushup(x);
int qry(int ql,int qr,int l = 1,int r = n,int x = 1)
if(ql <= l && r <= qr) return nd[x].sum;
pushdown(x);
int mid = (l+r)>>1,ans = 0;
if(ql <= mid) ans |= qry(ql,qr,l,mid,ls(x));
if(qr > mid) ans |= qry(ql,qr,mid+1,r,rs(x));
return ans;
int main(int argc, char** argv)
read(n,m);
rep(i,1,n) read(a[i]);
build(1,n,1);
while(m--)
int op;read(op);
if(op == 1)
int l,r;read(l,r);
printf("%d\\n",qry(l,r));
else
int l,r,x;read(l,r,x);
mdy(l,r,x);
return 0;
H
这题给定的线段,其实是一个特殊的有向图。之前某场abc考了一个有向图最短路的问题,就是在边权的基础上加了一个特性:某个节点a秒开启b秒关闭,无限交替。这个问题的关键性质就是:立刻走不会比”等一会再走“更差。
利用这个性质随便模拟一下就可以过了。判定是否要等待:
int tmp = ans % (pt[i].a + pt[i].b);
if(tmp < pt[i].a) ans += pt[i].a - tmp;
注意:别忘了先对位置升序排序。
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
#define rep(i,a,b) for(int i = (a);i <= (b);++i)
#define re_(i,a,b) for(int i = (a);i < (b);++i)
#define dwn(i,a,b) for(int i = (a);i >= (b);--i)
const int N = 1e5 + 5;
int n,m;
void dbg()puts("");
template<typename T, typename... R>void dbg(const T &f, const R &... r)
cout << f << " ";
dbg(r...);
template<typename Type>inline void read(Type &xx)
Type f = 1;char ch;xx = 0;
for(ch = getchar();ch < '0' || ch > '9';ch = getchar()) if(ch == '-') f = -1;
for(;ch >= '0' && ch <= '9';ch = getchar()) xx = xx * 10 + ch - '0';
xx *= f;
void read()
template<typename T,typename ...R>void read(T &x,R &...r)
read(x);
read(r...);
struct Nodeint p,a,b;pt[N];
bool cmp(Node &x,Node &y)return x.p 以上是关于牛客2021年七夕节比赛大部分题解(因数枚举模板线段树dp……)的主要内容,如果未能解决你的问题,请参考以下文章