Educational Codeforces Round 60 (Rated for Div. 2)(题解)

Educational Codeforces Round 60 (Rated for Div. 2)(题解)

A. Best Subsegment

题目大意

给出一段序列,找出这段序列的子序列,使得子序列的平均值尽可能大.如有平均值相等的情况,输出长度尽可能长的.问这种序列的长度

解题思路

即最大值最长连续有多长

AC代码

#include
using namespace std;
int main()
{
	int n;
	cin>>n;
	int maxn=0,cnt=0;
	int x;
	int ans=0;
	for(int i=1;i<=n;i++)
	{
		cin>>x;
		if(x>maxn)maxn=x,cnt=1,ans=1;
		else if(x==maxn)
		{
			cnt++;
			ans=max(ans,cnt);
		}
		else 
		{
			cnt=0;
		}
	}
	cout<<ans<<endl;
}

B. Emotes

题目大意

给出n个表情每个表情有一定的快乐值,问总共用出m个表情,每个表情不许使用超过k次的前提下,最大的欢乐值是多少

解题思路

欢乐值最大用k次,次大的用一次.即可

AC代码

#include
using namespace std;
#define int unsigned long long
int arr[200005];
int32_t main()
{
	int n,m,k;
	cin>>n>>m>>k;
	for(int i=1;i<=n;i++) cin>>arr[i];
	sort(arr+1,arr+1+n);
	int ans=0;
	int a=m%(k+1),b=m/(k+1);
	ans=(arr[n]*k+arr[n-1])*b+a*arr[n];
	cout<<ans<<endl;
}

C. Magic Ship

题目大意

有一天气预报会告知每天的风将会将你向上下左右中某个方向吹一个单位长度,每天你可以根据自主意愿向上下左右任意方向移动一个单位,也可以不动,给出一个初始坐标和一个终点目标,问最少需要多少天到达目标地点

解题思路

设一个预报周期在仅在风的影响下,x方向上行进tx,在y方向上行进ty,当前坐标和目标坐标x相距lx,y相聚ly,在一个周期的第i天在风向的引导下x方向行进了x[i],y方向行进了y[i],则假设当第k周期的第i天可以达到就需要满足
a b s ( l y − k ∗ t y − y [ i ] ) + a b s ( l x − k ∗ t x − x [ i ] ) ≤ k ∗ n + i abs(ly-k*ty-y[i])+abs(lx-k*tx-x[i])\le k*n+i abs(lyktyy[i])+abs(lxktxx[i])kn+i
为此二分这个k即可

AC代码

#include
#define int long long
using namespace std;
char s[100005];
int x[100005],y[100005];
int n;
int lx,ly;
int tx,ty;
int sw1(char a)
{
	if(a=='U') return 1;
	if(a=='D') return -1;
	if(a=='L') return 0;
	if(a=='R') return 0;
}
int sw2(char a)
{
	if(a=='U') return 0;
	if(a=='D') return 0;
	if(a=='L') return -1;
	if(a=='R') return 1;
}
int check(int k)
{
	int p,q;
	for(int i=1;i<=n;i++)
	{
		q=ly-k*ty-y[i];
		p=lx-k*tx-x[i];
		if(abs(p)+abs(q)<=k*n+i) return i;
	}
	return -1;
}
int32_t main()
{
	int x1,y1,x2,y2;
	cin>>x1>>y1>>x2>>y2;
	cin>>n;
	cin>>s+1;
	for(int i=1;i<=n;i++)
	{
		x[i]=x[i-1]+sw2(s[i]);
		y[i]=y[i-1]+sw1(s[i]);
	}
	tx=x[n],ty=y[n];
	lx=x2-x1,ly=y2-y1;
	int ans=-1;
	int l=0,r=1e9;
	int f;
	while(l<=r)
	{
		int mid=(l+r)/2;
		f=check(mid);
		if(f!=-1) ans=mid*n+f,r=mid-1;
		else l=mid+1;
	}
	cout<<ans<<endl;
}

D. Magic Gems

题目大意

现有一些魔法细菌,他们可以变成m个普通细菌,普通细菌不能变化.问有多少种方式选出一定数量的魔法细菌并使其中一部分分裂,使得最终的细菌数量为n

解题思路

显然对于n和m有答案 a n a_n an
a n = C n − 0 ∗ ( m − 1 ) 0 + C n − 1 ∗ ( m − 1 ) 1 + . . . + C n − k ∗ ( m − 1 ) k + . . . a_n=C_{n-0*(m-1)}^{0}+C_{n-1*(m-1)}^1+...+C_{n-k*(m-1)}^{k}+... an=Cn0(m1)0+Cn1(m1)1+...+Cnk(m1)k+...
直接对这个式子进行处理的话显然比较困难,此时比较自然的想法是寻找相似的式子
a n − ( m − 1 ) = C n − 1 ∗ ( m − 1 ) 0 + C n − 2 ∗ ( m − 1 ) 1 + . . . + C n − k ∗ ( m − 1 ) k − 1 + . . . a_{n-(m-1)}=C_{n-1*(m-1)}^{0}+C_{n-2*(m-1)}^1+...+C_{n-k*(m-1)}^{k-1}+... an(m1)=Cn1(m1)0+Cn2(m1)1+...+Cnk(m1)k1+...
根据组合相加的公式
C n m = C n − 1 m − 1 + C n − 1 m C_n^m=C_{n-1}^{m-1}+C_{n-1}^m Cnm=Cn1m1+Cn1m
可以将 a n + a n − ( m − 1 ) a_n+a_{n-(m-1)} an+an(m1)变换为
a n + a n − ( m − 1 ) = C n − 0 ∗ ( m − 1 ) 0 + C n + 1 − 1 ∗ ( m − 1 ) 1 + C n + 1 − 2 ∗ ( m − 1 ) 2 + . . . + C n + 1 − k ∗ ( m − 1 ) k + . . . a_n+a_{n-(m-1)}=C_{n-0*(m-1)}^0+C_{n+1-1*(m-1)}^1+C_{n+1-2*(m-1)}^2+...+C_{n+1-k*(m-1)}^{k}+... an+an(m1)=Cn0(m1)0+Cn+11(m1)1+Cn+12(m1)2+...+Cn+1k(m1)k+...
显然这个式子就是 a n + 1 a_{n+1} an+1

由此这个式子就可以通过
a n + 1 = a n + a n − ( m − 1 ) a_{n+1}=a_n+a_{n-(m-1)} an+1=an+an(m1)
再通过矩阵快速幂得到答案即可

AC代码

#include
using namespace std;
#define int long long 
const int mod=1e9+7;
typedef long long LL;
struct mat{
	LL m[110][110];
	mat(int x=0){memset(m,0,sizeof m);for(int i=1;i<110;i++)m[i][i]=x;}
	friend mat operator*(mat a,mat b){
		mat nxt;
		for(int i=1;i<110;i++)for(int j=1;j<110;j++)for(int k=1;k<110;k++)
			nxt.m[i][j]=(nxt.m[i][j]+1LL*a.m[i][k]*b.m[k][j]%mod)%mod;
		return nxt;
	}
};
int32_t main()
{
	int n,m;
	cin>>n>>m;
	mat a,b;
	a.m[1][1]=1;
	for(int i=1;i<=m-1;i++) b.m[i][i+1]=1;b.m[1][1]=1;b.m[m][1]=1;
	while(n)
	{
		if(n&1) a=a*b;
		b=b*b;
		n>>=1;
	}
	cout<<a.m[1][1]<<endl;
}

E. Decypher the String

题目大意

给出你一个变换过的字符串,你可以进行三次询问,每次询问给出一个字符串,其将对你进行询问的字符串进行相同的变换,问一开始给出的字符串的初始字符串

解题思路

每次给出26字母的循环,其中每个字母连续出现的次数为 1 , 26 , 2 6 2 1,26,26^2 1,26,262,由这种循环填满整个字符串,则对一个位置的字符设为c[3],其一定来自于 c [ 0 ] − ′ a ′ + 26 ∗ i , ( c [ 1 ] − ′ a ′ ) ∗ 26 + 2 6 2 ∗ j , ( c [ 2 ] − ′ a ′ ) ∗ 2 6 2 + 2 6 3 ∗ k c[0]-'a'+26*i,(c[1]-'a')*26+26^2*j,(c[2]-'a')*26^2+26^3*k c[0]a+26i,(c[1]a)26+262j,(c[2]a)262+263k,即一个点的原始位置设为x一定满足
x % 26 = c [ 0 ] − ′ a ′ x % ( 2 6 2 ) = c [ 1 ] − ′ a ′ x % ( 2 6 3 ) = c [ 2 ] − ′ a ′ x\%26=c[0]-'a'\\ x\%(26^2)=c[1]-'a'\\ x\%(26^3)=c[2]-'a' x%26=c[0]ax%(262)=c[1]ax%(263)=c[2]a
由此解出x即

这个式子可以直接通过相加得出x且 2 6 3 > 10000 26^3>10000 263>10000故有唯一解

AC代码

#include
using namespace std;
int main()
{
	string a;
	cin>>a;
	int len=a.size();
	char s[3][100005];
	for(int i=0;i<len;i++)
	{
		s[0][i]=(i%26+'a');
		s[1][i]=(i/26%26+'a');
		s[2][i]=(i/(26*26)%26+'a');
	}
	string t[3];
	for(int j=0;j<3;j++) cout<<"? "<<s[j]<<endl,cin>>t[j];
	vector<int> id;
	for(int i=0;i<len;i++) id.push_back((t[0][i]-'a')+26*(t[1][i]-'a')+26*26*(t[2][i]-'a'));
	char ans[100005];
	for(int j=0;j<len;j++) ans[id[j]]=a[j];
	cout<<"! "<<ans<<endl;
}

你可能感兴趣的:(套题题解,codeforce)