Loading

1019考试总结

T1

先将两个大数分开,很显然一个很小,一个是111....1这样的形式

第一个直接暴力枚举,第二个考虑转化为(10^k-1)/9这样的形式,然后求 9 的逆元,注意 9 对于 3 没有逆元,特判

#include <cstdio>
#include <iostream>
#include <string>

using namespace std;

long long ksm(long long a,long long b,long long p)
{
  long long res=1;
  while(b)
  {
    if(b&1) res=res*a%p;
    b>>=1;
    a=a*a%p;
  }
  return res;
}

string s;

long long ans,ap,p[5000010];

bool pr[5000010];

int cnt;

void init()
{
  for(int i=2;i<=5000000;i++)
  {
    if(!pr[i])
    {
      p[++cnt]=i;
      for(int j=2;i*j<=5000000;j++)
      {
        pr[i*j]=1;
      }
    }
  }
}

long long work(long long len,long long p)
{
  if(p==3) return len%3==0;
  return (ksm(10,len,p)-1+p)%p*ksm(9,p-2,p)%p==0;
}

int main()
{
  //freopen("candy.in","r",stdin);
  //freopen("candy.out","r",stdout);
  init();
  cin>>s;
  for(int i=0;i<s.size();i++) ans+=s[i]-'0';
  ap=ans;
  for(long long i=1;i<=cnt;i++)
  {
    if(ans%p[i]==0||work(s.size(),p[i]))
    {
      ap=p[i];
      break;
    }
  }
  printf("%lld",ap);
}

T2

大力dp,设dp[i][j][k]表示[i,j]对于k这个边界是否可行

没有打过的原因是打了一个假的n2实际n4的记忆化,看过主定理发现并不是我所想的复杂度

#include <cstdio>
#include <vector>
#include <cstring>

using namespace std;

int a[1010];

bool con[1010][1010];

bool f[510][510][510];

bool vis[510][510][510];

int n;

int gcd(int a,int b)
{
  while((a%=b)&&(b%=a));
  return a+b;
}

bool dfs(int l,int r,int now)
{
  if(vis[l][r][now]) return f[l][r][now];
  vis[l][r][now]=1;
  if(l>r) return f[l][r][now]=1;
  if(l==r) return f[l][r][now]=con[l][now];
  for(int i=l;i<=r;i++)
    if(con[i][now]&&dfs(l,i-1,i)&&dfs(i+1,r,i))
      return f[l][r][now]=1;
  return f[l][r][now]=0;
}

void work()
{
  memset(con,0,sizeof(con));
  memset(vis,0,sizeof(vis));
  memset(f,0,sizeof(f));
  for(int i=1;i<=n;i++)
    for(int j=1;j<=n;j++)
      if(gcd(a[i],a[j])!=1)
        con[i][j]=1;
  // for(int i=1;i<=n;i++)
  // {
  //   for(int j=1;j<=n;j++)
  //       printf("%d ",con[i][j]);
  //   printf("\n");
  // }
  bool flag=0;
  for(int i=1;i<=n;i++) if(dfs(1,i-1,i)&&dfs(i+1,n,i))
  {
    printf("Yes\n");
    return ;
  }
  printf("No\n");
}

int main()
{
  //freopen("tree.in","r",stdin);
  //freopen("tree.out","r",stdout);
  int t;
  scanf("%d",&t);
  while(t--)
  {
    memset(a,0,sizeof(a));
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    work();
  }
}

T3

LNOI原题

没a的原因是线段树在上传的时候没有更新(好像之前也出现过,这种东西还很难调,没有啥明确的可以指出是这个错误的

直接考虑前缀化询问,然后离线就行

#include <cstdio>
#include <algorithm>

using namespace std;

struct Segment
{
  long long val,tag;
}tree[500010<<2];

struct Edge
{
  int to,next;
}e[1000010];

struct Query
{
  int pos,id,pi;
  long long vf;
}wq[1000010];

int n,q;

int num,head[1000010];

int size[500010],fa[500010],son[500010],top[500010],p[500010],cnt,cnting;

long long ans[500010];

bool cmp(Query a,Query b)
{
  return a.pos<b.pos;
}

void addedge(int a,int b)
{
  e[++num].to=b;
  e[num].next=head[a];
  head[a]=num;
}

void pushdown(int u,int l,int r)
{
  int mid=(l+r)>>1;
  tree[u<<1].tag+=tree[u].tag;
  tree[u<<1|1].tag+=tree[u].tag;
  tree[u<<1].val+=(long long)(mid-l+1)*tree[u].tag%201314;
  tree[u<<1|1].val+=(long long)(r-mid)*tree[u].tag%201314;
  tree[u].tag=0;
}

long long findtree(int u,int l,int r,int x,int y)
{
  if(x<=l&&r<=y) return tree[u].val;
  if(tree[u].tag) pushdown(u,l,r);
  int mid=(l+r)>>1;
  long long ans=0;
  if(x<=mid) ans+=findtree(u<<1,l,mid,x,y);
  if(y>mid) ans+=findtree(u<<1|1,mid+1,r,x,y);
  return ans%201314;
}

void changetree(int u,int l,int r,int x,int y)
{
  if(x<=l&&r<=y)
  {
    tree[u].val+=(r-l+1);
    tree[u].val%=201314;
    tree[u].tag++;
    tree[u].tag%=201314;
    return ;
  }
  if(tree[u].tag) pushdown(u,l,r);
  int mid=(l+r)>>1;
  if(x<=mid) changetree(u<<1,l,mid,x,y);
  if(y>mid) changetree(u<<1|1,mid+1,r,x,y);
  tree[u].val=(tree[u<<1].val+tree[u<<1|1].val)%201314;
}

void dfs1(int u)
{
  size[u]=1;
  for(int i=head[u];i;i=e[i].next)
  {
    fa[e[i].to]=u;
    dfs1(e[i].to);
    size[u]+=size[e[i].to];
    if(size[e[i].to]>size[son[u]]) son[u]=e[i].to;
  }
}

void dfs2(int u,int t)
{
  top[u]=t;
  p[u]=++cnting;
  if(!son[u]) return ;
  dfs2(son[u],t);
  for(int i=head[u];i;i=e[i].next)
  {
    if(e[i].to^son[u])
    {
      dfs2(e[i].to,e[i].to);
    }
  }
}

void change(int u)
{
  while(u)
  {
    changetree(1,1,n,p[top[u]],p[u]);
    u=fa[top[u]];
  }
}

int query(int u)
{
  long long res=0;
  while(u)
  {
    res+=findtree(1,1,n,p[top[u]],p[u]);
    res%=201314;
    u=fa[top[u]];
  }
  return res;
}

int main()
{
  //freopen("elf.in","r",stdin);
  //freopen("elf.out","r",stdout);
  scanf("%d%d",&n,&q);
  for(int i=2;i<=n;i++)
  {
    int x;
    scanf("%d",&x);
    addedge(x,i);
  }
  for(int i=1;i<=q;i++)
  {
    int l,r,z;
    scanf("%d%d%d",&l,&r,&z);
    wq[++cnt].id=i;
    wq[cnt].pi=z;
    wq[cnt].pos=l-1;
    wq[cnt].vf=-1;
    wq[++cnt].id=i;
    wq[cnt].pi=z;
    wq[cnt].pos=r;
    wq[cnt].vf=1;
  }
  dfs1(1);
  dfs2(1,1);
  fa[1]=0;
  sort(wq+1,wq+cnt+1,cmp);
  int pl=1;
  while(wq[pl].pos==0&&pl<=cnt) pl++;
  for(int i=1;i<=n;i++)
  {
    change(i);
    while(wq[pl].pos==i&&pl<=cnt)
    {
      ans[wq[pl].id]+=wq[pl].vf*query(wq[pl].pi);
      ans[wq[pl].id]=((ans[wq[pl].id]%201314)+201314)%201314;
      pl++;
    }
  }
  for(int i=1;i<=q;i++) printf("%lld\n",ans[i]);
}
posted @ 2020-10-19 16:35  zzqDeco  阅读(162)  评论(0编辑  收藏  举报