8.24-8.25联赛模拟 解题报告

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了8.24-8.25联赛模拟 解题报告相关的知识,希望对你有一定的参考价值。

T1:

直接模拟,然后坐标相同的点的统计用sort来去重,用map等STL会TLE。。。

// MADE BY QT666
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<iostream>
#include<cstring>
using namespace std;
typedef long long ll;
const int N=2000050;
struct data{
  int x,y;
}g[N];
bool cmp(const data &a,const data &b){
  if(a.x==b.x) return a.y<b.y;
  return a.x<b.x;
}
int n,flag,ans,x,y,xt,yt,cnt;
int main(){
  freopen("loverfinding.in","r",stdin);
  freopen("loverfinding.out","w",stdout);
  scanf("%d%d%d%d%d",&n,&x,&y,&xt,&yt);
  g[++cnt]=(data){x,y};
  for(int i=1;i<=n;i++){
    int dx,dy;scanf("%d%d",&dx,&dy);
    int x1=g[cnt].x+dx,y1=g[cnt].y+dy;
    g[++cnt]=(data){x1,y1};
    if(x1==xt&&y1==yt){flag=1;break;}
  }
  if(!flag){puts("SingleDog");return 0;}
  sort(g+1,g+1+cnt,cmp);g[0].x=2147483647,g[0].y=2147483647;
  for(int i=1;i<=cnt;i++){
    if(g[i].x==g[i-1].x&&g[i].y==g[i-1].y) continue;
    ans++;
  }
  printf("%d\n",ans);
  return 0;
}

T2:

跟洛谷的灾后重建是一样的,都是动态加点的floyd,只不过这个题要把点和询问sort一遍。。。

把点按照消费指数从小到大的加入图中,然后以当前加入的点为中转站来更新其余两点间的距离。。。

因为中转站是从小往大加入的,所以当前加入的中转站k,一定是i->k,k->j路径上的消费指数的最大值(除开起点和终点)。。。

那么我们对于每个询问,只把消费指数<=c的商店加入图中,然后查询跟一个点距离不超过d的点即可。。。

复杂度O(n^3+q*n) 或者每加入一个中转站就把所有人的f[i]数组排序,询问时二分,复杂度为O(n^3log+q*log)。。。

注意邻接矩阵的Inf要>1e9,不然可能不联通的点也被统计进了答案。。(memset(f,127/3,sizeof(f))只有40分)。。。

// MADE BY QT666
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<iostream>
#include<cstring>
#define RG register
using namespace std;
typedef long long ll;
const int N=2000050;
struct data{
  int id,v;
}g[N];
struct Data{
  int s,c,d,id;
}q[N];
int f[300][300],n,m,T,ans[N],tmp;
bool cmp(const data &a,const data &b){
  if(a.v==b.v) return a.id<b.id;
  return a.v<b.v;
}
bool cmp2(const Data &a,const Data &b){
  return a.c<b.c;
}
int main(){
  freopen("snackstore.in","r",stdin);
  freopen("snackstore.out","w",stdout);
  scanf("%d%d%d",&n,&m,&T);
  for(RG int i=1;i<=n;i++) scanf("%d",&g[i].v),g[i].id=i;
  //memset(f,127/3,sizeof(f));
  for(int i=1;i<=n;i++)
    for(int j=1;j<=n;j++)
      f[i][j]=1e9+1;
  for(RG int i=1;i<=n;i++) f[i][i]=0;
  for(RG int i=1;i<=m;i++){
    int x,y,z;scanf("%d%d%d",&x,&y,&z);
    f[x][y]=min(f[x][y],z);f[y][x]=min(f[y][x],z);
  }
  for(RG int i=1;i<=T;i++) scanf("%d%d%d",&q[i].s,&q[i].c,&q[i].d),q[i].id=i;
  sort(g+1,g+1+n,cmp);sort(q+1,q+1+T,cmp2);int k=1;
  for(RG int p=1;p<=T;p++){
    while(g[k].v<=q[p].c&&k<=n){
      for(RG int i=1;i<=n;i++)
	for(RG int j=1;j<=n;j++){
	  f[i][j]=min(f[i][j],f[i][g[k].id]+f[g[k].id][j]);
	}
      k++;
    }
    RG int s=q[p].s,ret=0;
    for(RG int i=1;i<=n;i++) if(i!=s&&f[s][i]<=q[p].d) ret++;
    ans[q[p].id]=ret;
  }
  for(int i=1;i<=T;i++) printf("%d\n",ans[i]);
  return 0;
}

T3:弃了。。。

T4:包含关系构成了一个DAG,那么可以用拓扑排序或者记忆化搜索来模拟题目的意思。

// MADE BY QT666
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<iostream>
#include<cstring>
#include<queue>
using namespace std;
typedef long long ll;
const int N=3000050;
const int Mod=1e9+7;
int head[N],to[N],nxt[N],cnt,v[N],du[N],n;
void lnk(int x,int y){
  to[++cnt]=y,nxt[cnt]=head[x],head[x]=cnt;
}
queue<int> Q;
void topsort(){
  while(!Q.empty()){
    int x=Q.front();Q.pop();
    for(int i=head[x];i;i=nxt[i]){
      int y=to[i];(v[y]+=v[x])%=Mod;du[y]--;
      if(du[y]==0) Q.push(y);
    }
  }
}
int main(){
  freopen("three_squirrels.in","r",stdin);
  freopen("three_squirrels.out","w",stdout);
  scanf("%d",&n);
  for(int i=1;i<=n;i++){
    int k;scanf("%d",&k);
    for(int j=1;j<=k;j++){int y;scanf("%d",&y);lnk(y,i);du[i]++;}
  }
  v[0]=1;
  for(int i=0;i<=n;i++) if(!du[i]) Q.push(i);
  topsort();printf("%d\n",v[n]);
  return 0;
}

T5:

首先每一步跳得尽量的大答案一定会最大,因为(a+b)^2>a^2+b^2。。。

那么因为题目中相似子串的定义为前缀等于后缀,并且我们又要求一次跳得尽量的大,

所以每次跳跃其实就是在跳kmp的nxt数组(前缀等于后缀的最大长度)。。。所以先用kmp把nxt数组构出来。。。

然后我们要求两个前缀的距离最大,因为每个位置i,只会跳向nxt[i],那么这种移动关系构成了一棵树(每个点最多一个父亲)

这就是所谓的kmp树。

那么我们要求两个前缀间的最长距离,就是树的直径。通过两边bfs求解。。

// MADE BY QT666
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<iostream>
#include<cstring>
#include<queue>
using namespace std;
typedef long long ll;
const int N=3000050;
char s[N];
int len,fail[N];
int head[N],to[N],nxt[N],cnt,vis[N];
ll v[N],dis[N];
void lnk(int x,int y,ll z){
  to[++cnt]=y,nxt[cnt]=head[x],v[cnt]=z,head[x]=cnt;
  to[++cnt]=x,nxt[cnt]=head[y],v[cnt]=z,head[y]=cnt;
}
void make_nxt() {
  int j=0;  
  for(int i=2;i<=len;i++){  
    while(j&&s[j+1]!=s[i]) j=fail[j];  
    if(s[j+1]==s[i]) j++;  
    fail[i]=j;  
  }  
}
queue<int> Q;
void bfs(int x){
  for(int i=0;i<=len;i++) dis[i]=0,vis[i]=0;
  Q.push(x);vis[x]=1;
  while(!Q.empty()){
    int x=Q.front();Q.pop();
    for(int i=head[x];i;i=nxt[i]){
      int y=to[i];
      if(!vis[y]) dis[y]=dis[x]+v[i],vis[y]=1,Q.push(y);
    }
  }
}
ll sqr(ll x){return 1ll*x*x;}
int main(){
  freopen("savemzx.in","r",stdin);
  freopen("savemzx.out","w",stdout);
  scanf("%s",s+1);len=strlen(s+1);make_nxt();
  for(int i=1;i<=len;i++) lnk(fail[i],i,sqr(1ll*i-fail[i]));
  bfs(0);
  int rt1=0;ll Max=0;for(int i=0;i<=len;i++) if(dis[i]>Max) rt1=i,Max=dis[i];
  bfs(rt1);
  int rt2=rt1;ll ans=0;for(int i=0;i<=len;i++) if(dis[i]>ans) rt2=i,ans=dis[i];
  printf("%lld\n",ans);
  return 0;
}

T6:

万万没有想到这竟然是两道题目强行拼起来的。。。

首先这个题要维护的就是区间积,然后第一问要%p1,第二问要%phi(p2)(降幂)。。。

然后7-10个测试点都是可以用exgcd来求逆元的(肯定是互质的),所以可以直接用前缀积相除来实现。。。

前面的1-6个测试点直接用线段树来维护区间积,注意不能%0。。。

// MADE BY QT666
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<iostream>
#include<cstring>
using namespace std;
typedef long long ll;
const int N=3000050;
int n,m,k,mod,Mod,M;
ll a[N],mul[N];
ll qpow(ll x,ll y,ll mo){ll ret=1;while(y){if(y&1) (ret*=x)%=mo;(x*=x)%=mo;y>>=1;} return ret;}
void exgcd(ll a,ll b,ll &x,ll &y){
  if(!b) x=1,y=0;
  else exgcd(b,(a+b)%b,y,x),y-=x*(a/b);
}
void getphi(ll P){
  M=P;ll res=P;
  for(ll i=2;i*i<=P;i++)
    if(res%i==0) {
      (M/=i)*=i-1;
      while(res%i==0) res/=i;
    }
  if(res>1) (M/=res)*=res-1;
}
int ls[N],rs[N],rt,sz;
ll tr[N],tr2[N];
void pushup(int x){
  tr[x]=(tr[ls[x]]*tr[rs[x]])%mod;
  if(Mod) tr2[x]=(tr2[ls[x]]*tr2[rs[x]])%M;
}
void insert(int &x,int l,int r,int id){
  if(!x) x=++sz;
  if(l==r){tr[x]=tr2[x]=a[id];return;}
  int mid=(l+r)>>1;
  if(id<=mid) insert(ls[x],l,mid,id);
  else insert(rs[x],mid+1,r,id);
  pushup(x);
}
ll query1(int x,int l,int r,int xl,int xr){
  if(xl<=l&&r<=xr){return tr[x];}
  int mid=(l+r)>>1;
  if(xr<=mid) return query1(ls[x],l,mid,xl,xr);
  else if(xl>mid) return query1(rs[x],mid+1,r,xl,xr);
  else return query1(ls[x],l,mid,xl,mid)*query1(rs[x],mid+1,r,mid+1,xr)%mod;
}
ll query2(int x,int l,int r,int xl,int xr){
  if(xl<=l&&r<=xr){return tr2[x];}
  int mid=(l+r)>>1;
  if(xr<=mid) return query2(ls[x],l,mid,xl,xr);
  else if(xl>mid) return query2(rs[x],mid+1,r,xl,xr);
  else return query2(ls[x],l,mid,xl,mid)*query2(rs[x],mid+1,r,mid+1,xr)%M;
}
int main(){
  freopen("chocolatebox.in","r",stdin);
  freopen("chocolatebox.out","w",stdout);
  scanf("%d%d%d%d%d",&n,&m,&k,&mod,&Mod);getphi(Mod);
  for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
  if(mod==1e9+7||mod==996919243){
    mul[0]=1;
    for(int i=1;i<=n;i++) (mul[i]=mul[i-1]*a[i])%=mod;
    for(int i=1;i<=m;i++){
      int type,l,r;scanf("%d%d%d",&type,&l,&r);
      ll x,y;exgcd(mul[l-1],mod,x,y);ll inv=(x+mod)%mod;
      ll ans=mul[r]*inv%mod;printf("%lld\n",ans);
    }
  }
  else if(Mod==984359||Mod==988643){
    mul[0]=1;
    for(int i=1;i<=n;i++) (mul[i]=mul[i-1]*a[i])%=M;
    for(int i=1;i<=m;i++){
      int type,l,r;scanf("%d%d%d",&type,&l,&r);
      ll x,y;exgcd(mul[l-1],M,x,y);ll inv=(x+M)%M;
      ll ret=mul[r]*inv%M;ll ans=qpow(k,ret,Mod);printf("%lld\n",ans);
    }
  }
  else if(n<=500000){
    memset(tr,1,sizeof(tr));memset(tr2,1,sizeof(tr2));
    for(int i=1;i<=n;i++) insert(rt,1,n,i);
    for(int i=1;i<=m;i++){
      int type,l,r;scanf("%d%d%d",&type,&l,&r);
      if(type==1){
	ll ret=query1(rt,1,n,l,r);
	printf("%lld\n",ret);
      }
      else{
	ll ret=query2(rt,1,n,l,r);
	ll ans=qpow(k,ret,Mod);printf("%lld\n",ans);
      }
    }
  }
  return 0;
}

以上是关于8.24-8.25联赛模拟 解题报告的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ 4816 数字表格

解题报告 『占卜DIY(模拟)』

NOIP模拟2017.6.11解题报告

POJ 2260(模拟&贪心_B题)解题报告

2019模拟赛09场解题报告

一个蒟蒻的挣扎模拟赛2解题报告