zoukankan      html  css  js  c++  java
  • Codeforces Round #566 (Div. 2)

    前言

    md终于紫了,纪念一下

    A

    题意

    用若干(egin{matrix}Boxlacksquare\lacksquarelacksquareend{matrix})以及旋转(90^circ,180^circ,270^circ)的版本填充(3*n)的方格,问方案

    题解

    自己看代码,懒得写了

    	n=rd();
    	if(n&1) puts("0");
    	else
    	{
    		n>>=1;
    		cout<<(1ll<<n);
    	}
    

    B

    题意

    问一个字符矩阵是否存在一个加号,且其他格子为空

    题解

    模拟

    注意细节即可

    #include<bits/stdc++.h>
    #define db long double
    #define il inline
    #define re register
    
    using namespace std;
    const int N=500+10,mod=998244353;
    int rd()
    {
        int x=0,w=1;char ch=0;
        while(ch<'0'||ch>'9') {if(ch=='-') w=-1;ch=getchar();}
        while(ch>='0'&&ch<='9') {x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
        return x*w;
    }
    int n,m,tt;
    char cc[N][N];
    
    
    int main()
    {
    	n=rd(),m=rd();
    	for(int i=1;i<=n;++i) scanf("%s",cc[i]+1);
    	for(int i=1;i<=n;++i)
    		for(int j=1;j<=m;++j)
    			tt+=cc[i][j]=='*';
    	for(int i=2;i<n;++i)
    		for(int j=2;j<m;++j)
    			if(cc[i][j]=='*'&&cc[i-1][j]=='*'&&cc[i+1][j]=='*'&&cc[i][j-1]=='*'&&cc[i][j+1]=='*')
    			{
    				int cn=1;
    				for(int k=i-1;cc[k][j]=='*';--k) ++cn;
    				for(int k=i+1;cc[k][j]=='*';++k) ++cn;
    				for(int k=j-1;cc[i][k]=='*';--k) ++cn;
    				for(int k=j+1;cc[i][k]=='*';++k) ++cn;
    				puts(cn==tt?"YES":"NO");
    				return 0;
    			}
    	puts("NO");
    	return 0;
    }
    

    C

    题意

    定义鸡你太美为四个单词组成的,每行两个单词的东西,其中第一行第一个单词和第二行第一个单词元音字母((a,e,o,i,u))个数要相同,第一行第二个单词和第二行第二个单词元音字母个数要相同,每行最后一个元音字母要相同.现在给出一些单词,每个只能用一个,问最多拼出多少个鸡你太美并输出方案

    题解

    在单词中尽可能凑出元音字母个数相同最后一个元音相同的单词对,再从剩下的凑出元音字母个数相同的单词对,然后前者可以作为每行第一个以及第二个单词对,后者只能放第一个,所以记个数分别为(n,m),答案为(min(lfloorfrac{n+m}{2} floor,n)),方案就尽可能用后者放第一个构造即可

    #include<bits/stdc++.h>
    #define db long double
    #define il inline
    #define re register
    
    using namespace std;
    const int N=1e5+10,M=N*10;
    int rd()
    {
        int x=0,w=1;char ch=0;
        while(ch<'0'||ch>'9') {if(ch=='-') w=-1;ch=getchar();}
        while(ch>='0'&&ch<='9') {x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
        return x*w;
    }
    int n,m;
    char cc[M];
    string ss[N];
    int a[M][5];
    vector<int> ls[M][5];
    struct node{int x,y;};
    int res[M],to[128];
    vector<node> c1,c2;
    
    int main()
    {
    	memset(to,-1,sizeof(to));
    	to['a']=0;
    	to['e']=1;
    	to['i']=2;
    	to['o']=3;
    	to['u']=4;
    	n=rd();
    	for(int i=1;i<=n;++i)
    	{
    		scanf("%s",cc);
    		int len=strlen(cc);
    		int cn=0,la=0;
    		for(int j=0;j<len;++j)
    		{
    			ss[i].push_back(cc[j]);
    			if(to[(int)cc[j]]>=0)
    				++cn,la=to[(int)cc[j]];
    		}
    		m=max(m,cn);
    		if(cn) ++a[cn][la],ls[cn][la].push_back(i);
    	}
    	for(int i=1;i<=m;++i)
    		for(int j=0;j<=4;++j)
    		{
    			if(!a[i][j]) continue;
    			while(a[i][j]>1)
    			{
    				int xx=ls[i][j][a[i][j]-1],yy=ls[i][j][a[i][j]-2];
    				c1.push_back((node){xx,yy});
    				--a[i][j],--a[i][j];
    				ls[i][j].pop_back();
    				ls[i][j].pop_back();
    			}
    			if(a[i][j])
    			{
    				if(res[i]) c2.push_back((node){res[i],ls[i][j][0]}),res[i]=0;
    				else res[i]=ls[i][j][0];
    			}
    		}
    	int nn=c1.size(),mm=c2.size();
    	int ta=min((nn+mm)/2,nn);
    	printf("%d
    ",ta);
    	while(ta--)
    	{
    		node st,en;
    		en=c1[nn-1];
    		--nn,c1.pop_back();
    		if(mm)
    		{
    			st=c2[mm-1];
    			--mm,c2.pop_back();
    		}
    		else
    		{
    			st=c1[nn-1];
    			--nn,c1.pop_back();
    		}
    		cout<<ss[st.x]<<" "<<ss[en.x]<<endl<<ss[st.y]<<" "<<ss[en.y]<<endl;
    	}
    	return 0;
    }
    

    D

    题意

    给一棵树,要找一个点作为根,使得对于同种深度的点,度数都相同

    题解

    容易发现这样的点要么是整棵树的重心(也就是样例解释的点(3)),要么是一个叶子,满足从这个叶子沿着对应的从树上伸出去链走,走到的第一个不在这条链上的点,在去掉那条链后变成剩下树的重心(同时满足条件)

    也就是找到一个点,使得它作为根时其他儿子的子树都是满足条件且形态一样的树,或者有个儿子伸出去一条链.这个可以树哈希求出以某个点为根是子树的哈希值,然后换根dp求出子树以外的哈希值,就可以较方便的求解的

    口胡一时爽,改题3h直接火葬场

    #include<bits/stdc++.h>
    #define db long double
    #define uLL unsigned long long
    
    using namespace std;
    const int N=2e5+10;
    int rd()
    {
        int x=0,w=1;char ch=0;
        while(ch<'0'||ch>'9') {if(ch=='-') w=-1;ch=getchar();}
        while(ch>='0'&&ch<='9') {x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
        return x*w;
    }
    int to[N<<1],nt[N<<1],hd[N],dg[N],tot=1;
    void add(int x,int y)
    {
        ++tot,to[tot]=y,nt[tot]=hd[x],hd[x]=tot,++dg[x];
        ++tot,to[tot]=x,nt[tot]=hd[y],hd[y]=tot,++dg[y];
    }
    int n,sz[N],h[N],ans=-1;
    uLL f[N],g[N],bs=99991,bb[N];
    void dfs1(int x,int ffa)
    {
        if(dg[x]==1) h[x]=x;
        bool o=1;
        uLL pp=0;
        sz[x]=1;
        int szz=0,cn=0;
        for(int i=hd[x];i;i=nt[i])
        {
            int y=to[i];
            if(y==ffa) continue;
            dfs1(y,x);
            sz[x]+=sz[y];
            if(!h[x]) h[x]=h[y];
            if(!cn) szz=sz[y],pp=f[y];
            else if(sz[y]!=szz||f[y]!=pp) o=0;
            ++cn;
        }
        o&=dg[x]==1||(bool)pp;
        if(o)
        {
            while(cn--) f[x]=f[x]*bb[szz]+pp*szz;
            f[x]=f[x]*bs+1;
        }
        else f[x]=0;
        if(dg[x]>2) h[x]=0;
    }
    void dfs2(int x,int ffa)
    {
        bool o=1;
        uLL p1=0,p2=0;
        int s1=0,c1=0,s2=0,c2=0;
        if(ffa)
        {
            p1=g[x],s1=n-sz[x],c1=1;
            if(dg[x]<=2&&h[ffa]) h[x]=h[ffa];
        }
        for(int i=hd[x];i;i=nt[i])
        {
            int y=to[i];
            if(y==ffa) continue;
            if(!c1) p1=f[y],s1=sz[y],c1=1;
            else if(f[y]==p1) ++c1;
            else if(!c2) p2=f[y],s2=sz[y],c2=1;
            else if(f[y]==p2) ++c2;
            else o=0;
        }
        if(c1<c2||(c1==c2&&!p1)) swap(p1,p2),swap(s1,s2),swap(c1,c2);
        o&=(bool)p1&(c2<=1);
        if(o)
        {
            if(c1>1&&!c2)
            {
                printf("%d
    ",x);
                exit(0);
            }
            else
            {
                if(ffa&&g[x]==p2&&p2&&h[ffa]) {printf("%d
    ",h[ffa]);exit(0);} 
                uLL nw=0;
                bool o=c1==1;
                while(c1--) nw=nw*bb[s1]+p1*s1;
                nw=nw*bs+1;
                for(int i=hd[x];i;i=nt[i])
                {
                    int y=to[i];
                    if(y==ffa) continue;
                    if(f[y]==p2)
                    {
                        if(p2&&h[y]){printf("%d
    ",h[y]);exit(0);}
                        g[y]=nw;
                    }
                    else if(o&&f[y]==p1) g[y]=p2?p2*s2*bs+1:0;
                    dfs2(y,x);
                }
            }
        }
        else
        {
            for(int i=hd[x];i;i=nt[i])
            {
                int y=to[i];
                if(y==ffa) continue;
                dfs2(y,x);
            }
        }
    }
    
    int main()
    {
        /*wdnmd*/
        n=rd();
        bb[0]=1;
        for(int i=1;i<=n;++i)
        {
            bb[i]=bb[i-1]*bs;
        }
        for(int i=1;i<n;++i) add(rd(),rd());
        if(n<=2) {puts("1");return 0;}
        int rt=1;
        while(dg[rt]==1) ++rt;
        dfs1(rt,0);
        dfs2(rt,0);
        printf("%d
    ",ans);
        return 0;
    }
    

    E

    题意

    (f_i=c^{2i-6}f_{i-1}f_{i-2}f_{i-3}(i>4))

    已知(n,f_1,f_2,f_3,c),求(f_n)

    题解

    (n)很大,但是这个递推式很矩乘,考虑矩乘

    矩乘就要记录每一项的指数,但是指数的模数是(1e9+6),不好直接做,可以把所有数改用(mod 1e9+6)的原根表示,使用(BSGS)可以求出所有数对应的(g^x)
    (x),
    然后矩乘转移就完事了

    wc我在干嘛

    //嘤嘤嘤
    #include<bits/stdc++.h>
    #define db long double
    #define il inline
    #define re register
    #define LL long long
    
    using namespace std;
    const int N=60,g=5;
    LL rd()
    {
        LL x=0,w=1;char ch=0;
        while(ch<'0'||ch>'9') {if(ch=='-') w=-1;ch=getchar();}
        while(ch>='0'&&ch<='9') {x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
        return x*w;
    }
    int md=1e9+7,mod=md-1,nmd=500000003;
    int fpow(int a,int b,int mod){int an=1;while(b){if(b&1) an=1ll*an*a%mod;a=1ll*a*a%mod,b>>=1;} return an;}
    struct matrix
    {
        int a[9][9],n;
        matrix(){memset(a,0,sizeof(a)),n=0;}
        matrix operator * (const matrix &bb) const
    		{
    			matrix an;
    			an.n=n;
    			for(int i=0;i<n;++i)
    				for(int j=0;j<n;++j)
    				{
    					LL nw=0;
    					for(int k=0;k<n;++k) nw+=1ll*a[i][k]*bb.a[k][j];
    					an.a[i][j]=nw%mod;
    				}
    			return an;
    		}
        matrix operator ^ (const LL &bb) const
    		{
    			matrix an,a=*this;
    			an.n=n;
    			for(int i=0;i<n;++i) an.a[i][i]=1;
    			LL b=bb;
    			while(b)
    			{
    				if(b&1) an=an*a;
    				a=a*a,b>>=1;
    			}
    			return an;
    		}
    }aa,bb,cc,dd;
    map<LL,LL> ha;
    il LL bsgs(LL a,LL b,LL mod)
    {
    	ha.clear();
    	LL kk=sqrt(mod)+1,aa=b,ka=fpow(a,kk,mod);
    	for(int i=0;i<kk;++i) ha[aa]=i,aa=aa*a%mod;
    	aa=1;
    	for(int i=0;i<=kk;++i)
    	{
    		if(ha.find(aa)!=ha.end()&&i*kk-ha[aa]>=0) return i*kk-ha[aa];
    		aa=aa*ka%mod;
    	}
    	return -1;
    }
    
    LL n,x,y,z,c,ans=1;
    
    int main()
    {
    	n=rd(),x=rd(),y=rd(),z=rd(),c=rd();
    	int xx=bsgs(g,x,md),yy=bsgs(g,y,md),zz=bsgs(g,z,md),ccc=1ll*bsgs(g,c,md)*2;
    	aa.n=bb.n=3;
    	aa.a[0][0]=xx,aa.a[0][1]=yy,aa.a[0][2]=zz;
    	bb.a[0][2]=1;
    	bb.a[1][0]=bb.a[1][2]=1;
    	bb.a[2][1]=bb.a[2][2]=1;
    	aa=aa*(bb^(n-3));
    	ans=1ll*ans*fpow(g,aa.a[0][2],md)%md;
    	cc.n=dd.n=5;
    	cc.a[0][3]=cc.a[0][4]=ccc;
    	dd.a[0][2]=1;
    	dd.a[1][0]=dd.a[1][2]=1;
    	dd.a[2][1]=dd.a[2][2]=1;
    	dd.a[3][3]=dd.a[3][2]=1;
    	dd.a[4][3]=dd.a[4][4]=1;
    	cc=(cc*(dd^(n-3)));
    	ans=1ll*ans*fpow(g,cc.a[0][2],md)%md;
    	cout<<ans<<endl;
    	return 0; 
    }
    

    F

    题意

    求最小的整数(xin [a,b]),使得(|sin(frac{p}{q}pi x)|)最大

    题解

    妙蛙

    由所学的高中数学可以知道,(y=|sin(x)|)一个数(x)(mod pi)时越接近(frac{pi}{2})越大,在本题中就是求数(x),使得(frac{p}{q}pi xmod pi)最接近(frac{pi}{2}),这等价于要使得(2pxmod 2q)最接近(q).然后考虑分块,把(t=sqrt{b-a+1})作为块大小,设(g(x)=2pxmod 2q)然后预处理出二元组((g(a),a),(g(a+1),a+1)...(g(a+t-1),a+t-1)),按照(g)排序去重后就是一个(g)单调的序列,然后如果只查([a,a+t-1])的话就可以直接二分找到最接近(q)的位置.然后现在每次把询问区间后移(t),假设现在是([i,i+t-1]),那么只要求出(mod 2q)意义下最接近(q- 2p(i-a) mod 2q)的位置即可.最后一些剩余部分暴力即可

    #include<bits/stdc++.h>
    #define LL long long
    #define il inline
    #define re register
    
    using namespace std;
    const int N=80000+10;
    int rd()
    {
        int x=0,w=1;char ch=0;
        while(ch<'0'||ch>'9') {if(ch=='-') w=-1;ch=getchar();}
        while(ch>='0'&&ch<='9') {x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
        return x*w;
    }
    int l,r,n,p,q;
    struct node
    {
    	LL x;
    	int i;
    	bool operator < (const node &bb) const {return x!=bb.x?x<bb.x:i<bb.i;}
    }a[N];
    
    int main()
    {
    	int T=rd();
    	a[0].x=-1;
    	while(T--)
    	{
    		int ans=0,mx=1<<30;
    		l=rd(),r=rd(),p=rd(),q=rd();
    		n=r-l+1;
    		int kk=sqrt(n),mod=2*q;
    		for(int i=0;i<kk;++i) a[i+1]=(node){2ll*p*(l+i)%mod,i};
    		sort(a+1,a+kk+1);
    		int m=0;
    		for(int i=1;i<=kk;++i)
    			if(a[i].x!=a[i-1].x) a[++m]=a[i];
    		int ii;
    		for(ii=l;ii+kk-1<=r;ii+=kk)
    		{
    			int zz=((1ll*q-2ll*p*(ii-l)%mod)%mod+mod)%mod;
    			int ps=upper_bound(a+1,a+m+1,(node){zz,0})-a,nw;
    			ps=(ps-1)%m+1;
    			nw=min(abs(1ll*a[ps].x-zz),min(abs(1ll*a[ps].x+mod-zz),abs(1ll*a[ps].x-mod-zz)));
    			if(mx>nw||(mx==nw&&ans>a[ps].i+ii)) ans=a[ps].i+ii,mx=nw;
    			ps=(ps+m-2)%m+1;
    			nw=min(abs(1ll*a[ps].x-zz),min(abs(1ll*a[ps].x+mod-zz),abs(1ll*a[ps].x-mod-zz)));
    			if(mx>nw||(mx==nw&&ans>a[ps].i+ii)) ans=a[ps].i+ii,mx=nw;
    		}
    		while(ii<=r)
    		{
    			int nw=abs(2ll*p*ii%mod-q);
    			if(mx>nw||(mx==nw&&ans>ii)) ans=ii,mx=nw;
    			++ii;
    		}
    		printf("%d
    ",ans);
    	}
    	return 0; 
    }
    
  • 相关阅读:
    【题解】【模板】矩阵级数
    【题解】P2048 [NOI2010]超级钢琴
    【题解】[APIO2009]会议中心
    【题解】[P4178 Tree]
    【题解】扑克牌游戏
    【题解】quake
    【题解】cycle
    从不浪费——分治总结
    【题解】Painting Fence
    【题解】[CJOI2019Chebnear]
  • 原文地址:https://www.cnblogs.com/smyjr/p/11013056.html
Copyright © 2011-2022 走看看