zoukankan      html  css  js  c++  java
  • EZ 2018 04 21 NOIP2018 模拟赛(十) -LoliconAutomaton的退役赛

    难得的一次Unrated,避免了重回1500的尴尬

    其实题目都还可以,但只不过所有人T1都炸了可能是数据的锅(假的)

    而且我因为T1SB的把T2弃了,没想到是千年水题

    T3莫名爆炸,然后TM的40分(再一次感谢Unrated)

    链接

    T1

    题意很简单,主要是思想太牛逼

    当时一直在找规律,浪费了2hours。最后搞了一个O(n)的递推然后炸掉

    先讲一下递推

    • f[i][0]表示到第i轮时不经过1号点的方案数

    • f[i][1]表示到第i轮时经过过1号店且当前不在1号点的方案数

    • f[i][2]表示到第i轮时经过过1号店且当前在1号点的方案数

    所以:

    • 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]

    其实还可以滚动优化,而且还有维数更小的

    递推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;
    }
    

    满分算法:

    令a[t]表示t轮以后回到kid1的方法数

    考虑到进行到t轮时会有(n−1)^t种传法,因此不回到kid1的方法数就
    有(n−1)^t−a[t]种,而除了kid1的小孩在下一轮都可以传给kid1,因此
    a[t]+1=(n−1)^t-a[t],即a[t]+a[t+1]=(n−1)^t

    ⽤特征根法解这个递推关系可以得到答案是

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

    因此快速幂+逆元即可

    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

    类最小生成树裸题,然而我并没有看出来

    题意简化后找一条连接在S到T的路径,使得上面的最长的边最短

    将边排序后开一个并查集一条一条地加进去知道S与T联通即可

    这里偷懒了一下,懒得写Trie或是Hash了,直接开了map

    主要是距离的计算不要写错

    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

    这道题就是一道数据结构综合的毒瘤题了

    并查集判连通性+离线建树+二进制处理数+树链剖分+线段树

    首先这种把颜色转化成二进制再或(|)一下的题目也有类似的思想:Luogu P1558,只不过那道题是线性的,而这里变成了树上操作

    所以我们自然想到LCT,但是其实这道题不用LCT也行(%%%X_o_r dalao LCT A了此题)

    我们离线建树,用并查集判断操作的合法性

    然后直接把树按原来的点权建出来

    接下来对于修改树剖后直接单点修改即可,查询就是线段树上区间查询

    CODE(真心累)

    #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('
    '); else puts("-1");
    		}
    	}
    	return 0;
    }
    

    发现我的树剖+线段树竟然远快于X_o_r dalao的LCT+Splay

  • 相关阅读:
    thinkphp使用ajax
    thinkphp修改和删除数据
    thinkphp添加数据
    thinkphp中的查询语句
    thinkphp模型
    空控制器的处理
    thinkphp3.2.3版本文件目录及作用
    12月18日Smarty文件缓存
    12月15日smarty模板基本语法
    12月13日上午Smarty模版原理
  • 原文地址:https://www.cnblogs.com/cjjsb/p/8994826.html
Copyright © 2011-2022 走看看