【前言】
组队CF之帮wyl上橙,我和sc打小号上紫。
结果sc成功FST两题,wyl成功skipped。
我的小号幸存了qwq。
【题目】
原题地址
特判一下 d d d是不是在 [ l , r ] [l,r] [l,r]中,如果是那么答案就是 x ∗ ( r x + 1 ) x*(\frac r x +1) x∗(xr+1)
#include
#define mkp make_pair
#define pb push_back
#define fi first
#define se second
using namespace std;
typedef double db;
typedef long long ll;
typedef pair<int,int> pii;
const int INF=0x3f3f3f3f;
int read()
{
int ret=0,f=1;char c=getchar();
while(!isdigit(c)) {if(c=='-')f=0;c=getchar();}
while(isdigit(c)) ret=ret*10+(c^48),c=getchar();
return f?ret:-ret;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("A.in","r",stdin);
freopen("A.out","w",stdout);
#endif
int T=read();
while(T--)
{
int l=read(),r=read(),x=read();
if(x<l || x>r){printf("%d\n",x);}
else printf("%d\n",(r/x+1)*x);
}
return 0;
}
模拟。
#include
#define mkp make_pair
#define pb push_back
#define fi first
#define se second
using namespace std;
typedef double db;
typedef long long ll;
typedef pair<int,int> pii;
const int INF=0x3f3f3f3f,N=1e6+10;
int p[10],ans;
char s[N];
int read()
{
int ret=0,f=1;char c=getchar();
while(!isdigit(c)) {if(c=='-')f=0;c=getchar();}
while(isdigit(c)) ret=ret*10+(c^48),c=getchar();
return f?ret:-ret;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("B.in","r",stdin);
freopen("B.out","w",stdout);
#endif
scanf("%s",s);;int n=strlen(s);
memset(p,-1,sizeof(p));
for(int i=0;i<n;++i) if(s[i]=='[') {p[1]=i;break;}
for(int i=n-1;~i;--i) if(s[i]==']') {p[2]=i;break;}
if(p[1]>p[2] || p[1]==-1 || p[2]==-1){puts("-1");return 0;}
for(int i=p[1]+1;i<p[2];++i) if(s[i]==':'){p[3]=i;break;}
for(int i=p[2]-1;i>p[1];--i) if(s[i]==':'){p[4]=i;break;}
if(p[3]==-1 || p[4]==-1 || p[3]==p[4]) {puts("-1");return 0;}
for(int i=p[3]+1;i<p[4];++i) if(s[i]=='|') ++ans;
printf("%d\n",ans+4);
return 0;
}
按左端点排序,判断和上一条线段位置关系分组。
若一条线段被另一条包含在过程中可以判掉。
#include
#define mkp make_pair
#define pb push_back
#define fi first
#define se second
using namespace std;
typedef double db;
typedef long long ll;
typedef pair<int,int> pii;
const int INF=0x3f3f3f3f,N=1e5+10;
int n,bl[N];
int read()
{
int ret=0,f=1;char c=getchar();
while(!isdigit(c)) {if(c=='-')f=0;c=getchar();}
while(isdigit(c)) ret=ret*10+(c^48),c=getchar();
return f?ret:-ret;
}
struct seg
{
int l,r,id;
seg(int _l=0,int _r=0,int _id=0):l(_l),r(_r),id(_id){}
}a[N];
bool cmp(const seg&a,const seg&b)
{
return a.l<b.l || (a.l==b.l && a.r<b.r);
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("C.in","r",stdin);
freopen("C.out","w",stdout);
#endif
int T=read();
while(T--)
{
n=read();
for(int i=1;i<=n;++i) a[i].l=read(),a[i].r=read(),a[i].id=i;
sort(a+1,a+n+1,cmp);
for(int i=1;i<=n;++i) bl[i]=-1;
int las=0;
for(int i=1;i<=n;++i)
{
//cerr<
if(a[i].l>=a[las].l && a[i].r<=a[las].r) {bl[a[i].id]=bl[a[las].id];continue;}
if(a[i].l>a[las].r) bl[a[i].id]=bl[a[las].id]^1;
else bl[a[i].id]=bl[a[las].id];
las=i;
}
bool fg=0;
for(int i=1;i<=n;++i) if(bl[a[i].id]==0){fg=1;break;}
if(!fg){puts("-1");}
else {for(int i=1;i<=n;++i)printf("%d ",bl[i]+1);puts("");}
}
return 0;
}
枚举质因子, bfs \text{bfs} bfs直径。注意多余的边和点什么的不要经过。
#include
#define mkp make_pair
#define pb push_back
#define fi first
#define se second
using namespace std;
typedef double db;
typedef long long ll;
typedef pair<int,int> pii;
const int INF=0x3f3f3f3f,N=2e5+10;
int tot,n,pnum,rt,ans;
int bo[N],head[N],pri[N],dis[N],a[N];
map<int,bool>mp;
queue<int>q;
int read()
{
int ret=0,f=1;char c=getchar();
while(!isdigit(c)) {if(c=='-')f=0;c=getchar();}
while(isdigit(c)) ret=ret*10+(c^48),c=getchar();
return f?ret:-ret;
}
struct Tway{int v,w,nex;}e[N<<1];
void add(int u,int v,int w)
{
e[++tot]=(Tway){v,w,head[u]};head[u]=tot;
e[++tot]=(Tway){u,w,head[v]};head[v]=tot;
}
int gcd(int x,int y){return y?gcd(y,x%y):x;}
void init()
{
for(int i=2;i<N;++i)
{
if(!bo[i]) pri[++pnum]=i;
for(int j=1;j<=pnum && i*pri[j]<N;++j)
{
bo[i*pri[j]]=1;
if(!(i%pri[j])) break;
}
}
}
int bfs(int x,int p)
{
q.push(x);mp.clear();mp[x]=1;dis[x]=1;
int res=1;
while(!q.empty())
{
int u=q.front();q.pop();
for(int i=head[u];i;i=e[i].nex)
{
int v=e[i].v,w=e[i].w;
//cerr<
if(mp[v] || gcd(p,w)==1) continue;
dis[v]=dis[u]+1;rt=v;res=dis[v];mp[v]=1;
}
}
return res;
}
void findtree(int x,int p)
{
//cerr<
rt=0;bfs(x,p);
int res=bfs(rt,p);
ans=max(ans,res);
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("D.in","r",stdin);
freopen("D.out","w",stdout);
#endif
n=read();init();
for(int i=1;i<=n;++i) a[i]=read();
for(int i=1;i<n;++i)
{
int u=read(),v=read();
add(u,v,gcd(a[u],a[v]));
}
for(int p=1;p<=pnum;++p)
{
memset(dis,0,sizeof(dis));
for(int i=1;i<=n;++i) if(!dis[i] && gcd(a[i],pri[p])>1) findtree(i,pri[p]);
}
printf("%d\n",ans);
return 0;
}
将短边放前面,记录最大值判断一下。
#include
#define mkp make_pair
#define pb push_back
#define fi first
#define se second
using namespace std;
typedef double db;
typedef long long ll;
typedef pair<int,int> pii;
const int INF=0x3f3f3f3f;
int m,mxx,mxy;
int read()
{
int ret=0,f=1;char c=getchar();
while(!isdigit(c)) {if(c=='-')f=0;c=getchar();}
while(isdigit(c)) ret=ret*10+(c^48),c=getchar();
return f?ret:-ret;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("E.in","r",stdin);
freopen("E.out","w",stdout);
#endif
m=read();
while(m--)
{
char op[2];int x,y;
scanf("%s%d%d",op,&x,&y);
if(x>y) swap(x,y);
if(op[0]=='+') mxx=max(mxx,x),mxy=max(mxy,y);
else puts((mxx<=x && mxy<=y)?"YES":"NO");
}
return 0;
}
我们设 f i , j , k f_{i,j,k} fi,j,k表示从 i i i城市到 j j j城市,加油 k k k次,需要跑的最远一段路程。
显然 f i , i + 1 , 1 = a i + 1 − a i f_{i,i+1,1}=a_{i+1}-a_i fi,i+1,1=ai+1−ai
若我们固定了 i i i,当 k k k越大,最后一次加油的位置一定单调右移。
于是我们可以枚举这一阶段最后一次加油是在什么地方,随着这个位置右移,上一阶段最后一次加油位置一定也右移。
这个东西相当于将行程拆成了两部分 i − > j , j − > k i->j,j->k i−>j,j−>k。
转移也没什么好说的。
复杂度就是 O ( n 3 + m ) O(n^3+m) O(n3+m)的了。
#include
#define mkp make_pair
#define pb push_back
#define fi first
#define se second
using namespace std;
typedef double db;
typedef long long ll;
typedef pair<int,int> pii;
const int INF=0x3f3f3f3f,N=405;
int n,m,a[N],f[N][N][N];
ll ans;
int read()
{
int ret=0,f=1;char c=getchar();
while(!isdigit(c)) {if(c=='-')f=0;c=getchar();}
while(isdigit(c)) ret=ret*10+(c^48),c=getchar();
return f?ret:-ret;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("F.in","r",stdin);
freopen("F.out","w",stdout);
#endif
n=read();m=read();
for(int i=1;i<=n;++i) a[i]=read();
for(int i=1;i<n;++i)
{
for(int j=i+1;j<=n;++j) f[i][j][1]=a[j]-a[i];
for(int t=2;t+i<=n;++t)
{
int las=i+t-1;
for(int j=i+t;j<=n;++j)
{
while(las+1<j && max(f[i][las][t-1],a[j]-a[las])>max(f[i][las+1][t-1],a[j]-a[las+1])) ++las;
f[i][j][t]=max(f[i][las][t-1],a[j]-a[las]);
}
}
}
for(int i=1;i<=m;++i)
{
int s=read(),t=read(),c=read(),r=read();
ans=max(ans,(ll)f[s][t][min(t-s,r+1)]*c);
}
printf("%lld\n",ans);
return 0;
}
这是一道线性基裸题。
首先无解当且仅当所有数异或为0,否则显然可以构造出解。
我们只需要先让所有数先做一个前缀异或,然后按顺序插入线性基即可。
最后线性基中的基底个数就是答案。
#include
#define mkp make_pair
#define pb push_back
#define fi first
#define se second
using namespace std;
typedef double db;
typedef long long ll;
typedef pair<int,int> pii;
const int INF=0x3f3f3f3f,N=3e5+10;
int n,a[N];
int read()
{
int ret=0,f=1;char c=getchar();
while(!isdigit(c)) {if(c=='-')f=0;c=getchar();}
while(isdigit(c)) ret=ret*10+(c^48),c=getchar();
return f?ret:-ret;
}
void getfail(){puts("-1");exit(0);}
struct LinearBase
{
int ans,b[100];
void insert(int x)
{
int i,j;
for(i=30;~i;i--) if(x>>i&1)
{
if(b[i]) x^=b[i];
else break;
}
if(!x) return;
b[i]=x;++ans;
for(j=i-1;~j;j--) if(b[i]>>j&1) b[i]^=b[j];
for(j=i+1;j<31;j++) if(b[j]>>i&1) b[j]^=b[i];
}
}T;
int main()
{
#ifndef ONLINE_JUDGE
freopen("F.in","r",stdin);
freopen("F.out","w",stdout);
#endif
n=read();
for(int i=0;i<n;++i) a[i]=read();
for(int i=1;i<n;++i) a[i]^=a[i-1];
if(!a[n-1])getfail();
for(int i=0;i<n;++i) T.insert(a[i]);
printf("%d\n",T.ans);
return 0;
}