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; 
}
原文地址:https://www.cnblogs.com/smyjr/p/11013056.html