EZ 2018 04 21 NOIP2018 Mock Competition (10) -LoliconAutomaton's Retirement Competition

A rare Unrated , avoiding the embarrassment of returning to 1500

In fact, the title is OK, but everyone's T1 is blown up ,May be the pot of data(fake)

And I gave up T2 because of T1 SB , I didn't expect it to be a thousand-year water problem

T3 exploded inexplicably, then TM's 40 (thanks again to Unrated)

T1

The meaning of the question is very simple, the main reason is that the thinking is too arrogant

At that time, I was looking for a pattern and wasted 2hours. Finally, I did an O(n) recursion and then blew it up

Let's talk about recursion

  • f[i][0] represents the number of solutions that do not pass through point 1 by the time of the i-th round

  • f[i][1] represents the number of solutions that have passed through the No. 1 store and are currently not at the No. 1 point by the i-th round

  • f[i][2] represents the number of plans that have passed the No. 1 store and are currently at the No. 1 point by the i-th round

so:

  • f[i][0]=f[i-1][0]*(n-2)

  • f[i][1]=f[i-1][2]*(n-1)+f[i-1][1]*(n-2)

  • f[i][2]=f[i-1][1]+f[i-1][0]

In fact, it can also be optimized by rolling, and there are also smaller dimensions

recursion CODE

#include<cstdio>
const int P=1e9+7;
long long n,t,f[100005][3];
int main()
{
    scanf("%lld%lld",&n,&t);
    register int i;
    n%=P; t%=P;
    for (f[1][0]=n-1,i=2;i<=t;++i)
    {
        f[i][0]=(f[i-1][0]*(n-2))%P;
        f[i][1]=(f[i-1][2]*(n-1)+f[i-1][1]*(n-2))%P;
        f[i][2]=(f[i-1][1]+f[i-1][0])%P;
    }
    printf("%lld",(f[t-1][0]+f[t-1][1])%P);
    return 0;
}

Full score algorithm:

Let a[t] denote the number of ways to return to kid1 after round t

Considering that there will be (n−1)^t methods to pass when the t round is reached, so
there are , and the children except kid1 are in the next One round can be passed to kid1, so
a[t]+1=(n−1)^ta[t], that is, a[t]+a[t+1]=(n−1)^t

Solving this recurrence relationship with the eigenroot method can get the answer:

((n-1)^t+(-1)^t*(n-1))/n

So fast power + inverse can be

CODE

#include<cstdio>
using namespace std;
typedef long long LL;
const LL P=1e9+7;
LL n,t,ans;
inline LL quick_pow(LL x,LL p)
{
    LL tot=1;
    while (p)
    {
        if (p&1) tot=(tot*x)%P;
        x=(x*x)%P; p/=2;
    }
    return tot;
}
int main()
{
    scanf("%lld%lld",&n,&t); n%=P;
    ans=quick_pow(n-1,t);
    if (t&1) ans=(ans-n+1+P)%P; else ans=(ans+n-1+P)%P;
    printf("%lld",(ans*quick_pow(n,P-2))%P);
    return 0;
}

T2

Class minimum spanning tree bare question, but I didn't see it

After the problem is simplified, find a path connecting S to T so that the longest side above is the shortest

After sorting the edges, open one and check the sets and add them one by one until S and T are connected.

I'm lazy here, I'm too lazy to write Trie or Hash, so I open the map directly

The main reason is that the calculation of the distance should not be wrong

CODE

#include<cstdio>
#include<map>
#include<string>
#include<algorithm>
#include<cmath>
using namespace std;
typedef double DB;
const int N=3005;
map <string,int> rat;
struct data
{
    int l,r;
    DB s;
}a[N*N];
int n,x[N],y[N],r[N],cnt,father[N],s,t;
DB ans;
char temp[10];
inline void read(int &x)
{
    x=0; char ch=getchar(); int flag=1;
    while (ch<'0'||ch>'9') { if (ch=='-') flag=-1; ch=getchar(); }
    while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    x*=flag;
}
inline DB max(DB a,DB b)
{
    return a>b?a:b;
}
inline void add(int p,int q)
{
    a[++cnt].l=p; a[cnt].r=q;
    a[cnt].s=max(0.00,(DB)sqrt((DB)(x[p]-x[q])*(x[p]-x[q])+(DB)(y[p]-y[q])*(y[p]-y[q]))-r[p]-r[q]);
}
inline bool comp(data a,data b)
{
    return a.s<b.s;
}
inline int getfather(int k)
{
    return father[k]==k?k:father[k]=getfather(father[k]);
}
int main()
{
    //freopen("B.in","r",stdin); freopen("B.out","w",stdout);
    register int i,j;
    for (read(n),i=1;i<=n;++i)
    {
        scanf("%s",&temp); rat[temp]=i; father[i]=i;
        read(x[i]); read(y[i]); read(r[i]);
        for (j=1;j<i;++j)
        add(i,j);
    }
    scanf("%s",&temp); s=rat[temp]; 
    scanf("%s",&temp); t=rat[temp];
    sort(a+1,a+cnt+1,comp);
    for (i=1;i<=cnt;++i)
    {
        int fx=getfather(a[i].l),fy=getfather(a[i].r);
        if (fx!=fy)
        {
            ans=a[i].s;
            father[fx]=fy;
        }
        if (getfather(s)==getfather(t)) break;
    }
    printf("%.6lf",ans);
    return 0;
}

T3

This problem is a cancer problem of data structure synthesis.

And check the connectivity of set judgment + offline tree building + binary processing number + tree chain division + line segment tree

First of all, this problem of converting colors into binary and then OR (|) has a similar idea: Luogu P1558 , but that problem is linear, and here it becomes an operation on a tree

So we naturally think of LCT , but in fact, this question does not need LCT (%%%X_o_r dalao LCT A has this question)

We build trees offline, and use union check to judge the legitimacy of the operation

Then directly build the tree according to the original point weight

Next, after modifying the tree section, you can directly modify it with a single point. The query is the interval query on the line segment tree.

CODE (really tired)

#include<cstdio>
#include<cstring>
using namespace std;
typedef long long LL;
const int N=100005;
struct edge
{
    int to,next;
}e[N<<1];
struct ques
{
    int opt,x,y;
    bool est;
}q[3*N];
LL tree[N<<2];
int n,m,head[N],father[N],a[N],root,cnt,size[N],dep[N],son[N],id[N],top[N],s[N],tot;
inline char tc(void)
{
    static char fl[100000],*A=fl,*B=fl;
    return A==B&&(B=(A=fl)+fread(fl,1,100000,stdin),A==B)?EOF:*A++;
}
inline void read(int &x)
{
    x=0; char ch=tc();
    while (ch<'0'||ch>'9') ch=tc();
    while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=tc();
}
inline void write(int x)
{
    if (x/10) write(x/10);
    putchar(x%10+'0');
}
inline void add(int x,int y)
{
    e[++cnt].to=y; e[cnt].next=head[x]; head[x]=cnt;
}
inline int getfather(int k)
{
    return father[k]==k?k:father[k]=getfather(father[k]);
}
inline void up(int root)
{
    tree[root]=tree[root<<1]|tree[root<<1|1];
}
inline void build(int root,int l,int r)
{
    if (l==r)
    {
        tree[root]=(LL)1<<s[l];
        return;
    }
    int mid=l+r>>1;
    build(root<<1,l,mid); build(root<<1|1,mid+1,r);
    up(root);
}
inline void modify(int root,int l,int r,int id,int k)
{
    if (l==r)
    {
        tree[root]=(LL)1<<k;
        s[l]=k;
        return;
    }
    int mid=l+r>>1;
    if (id<=mid) modify(root<<1,l,mid,id,k); else modify(root<<1|1,mid+1,r,id,k);
    up(root);
}
inline LL query(int root,int l,int r,int beg,int end)
{
    if (l>=beg&&r<=end) return tree[root];
    int mid=l+r>>1;
    LL res=0;
    if (beg<=mid) res|=query(root<<1,l,mid,beg,end);
    if (end>mid) res|=query(root<<1|1,mid+1,r,beg,end);
    return res;
}
inline int count(LL x)
{
    int res=0;
    while (x) 
    {
        res+=x&1;
        x/=2;
    }
    return res;
}
inline void swap(int &a,int &b)
{
    int t=a; a=b; b=t;
}
inline void DFS1(int now,int fa,int d)
{
    size[now]=1; father[now]=fa; dep[now]=d;
    int res=-1;
    for (register int i=head[now];i!=-1;i=e[i].next)
    if (e[i].to!=fa)
    {
        DFS1(e[i].to,now,d+1);
        size[now]+=size[e[i].to];
        if (size[e[i].to]>res) res=size[e[i].to],son[now]=e[i].to;
    }
}
inline void DFS2(int now,int topf)
{
    id[now]=++tot; s[tot]=a[now]; top[now]=topf;
    if (!son[now]) return;
    DFS2(son[now],topf);
    for (register int i=head[now];i!=-1;i=e[i].next)
    if (e[i].to!=father[now]&&e[i].to!=son[now]) DFS2(e[i].to,e[i].to);
}
inline void updata(int x,int z)
{
    modify(1,1,tot,id[x],z);
}
inline int get_sec(int x,int y)
{
    LL res=0;
    while (top[x]!=top[y])
    {
        if (dep[top[x]]<dep[top[y]]) swap(x,y);
        res|=query(1,1,tot,id[top[x]],id[x]);
        x=father[top[x]];
    }
    if (dep[x]<dep[y]) swap(x,y);
    res|=query(1,1,tot,id[y],id[x]);
    return count(res);
}
int main()
{
    //freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
    register int i;
    memset(head,-1,sizeof(head));
    memset(e,-1,sizeof(e));
    read(n); read(m);
    for (i=1;i<=n;++i)
    read(a[i]),father[i]=i;
    for (i=1;i<=m;++i)
    {
        read(q[i].opt); read(q[i].x); read(q[i].y);
        int fx=getfather(q[i].x),fy=getfather(q[i].y);
        if (q[i].opt==1)
        {
            if (fx!=fy) father[fx]=fy,q[i].est=1,add(q[i].x,q[i].y),add(q[i].y,q[i].x),root=q[i].x;
        } else 
        {
            if (fx==fy) q[i].est=1;
        }
    }
    memset(father,0,sizeof(father));
    DFS1(root,-1,0);
    DFS2(root,root);
    build(1,1,tot);
    for (i=1;i<=m;++i)
    {
        if (q[i].opt==1&&q[i].est) 
        {
            int res=s[id[q[i].x]]+s[id[q[i].y]]>>1;
            updata(q[i].x,res); updata(q[i].y,res);
        }
        if (q[i].opt==2)
        {
            if (q[i].est) write(get_sec(q[i].x,q[i].y)),putchar('\n'); else puts("-1");
        }
    }
    return 0;
}

I found that my tree section + line segment tree is much faster than X_o_r dalao's LCT+Splay

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325382350&siteId=291194637