Educational Codeforces Round 173 (Rated for Div. 2) - Codeforces

发布于:2025-02-11 ⋅ 阅读:(57) ⋅ 点赞:(0)

Educational Codeforces Round 173 (Rated for Div. 2) - Codeforces

Problem - A - Codeforces

签到题目

Problem - B - Codeforces

数学

被小学奥数薄纱力…

给出一个由 n ! n! n! d d d组成的整数,看他能否被十以内的奇数整除

1 1 1肯定是答案

一个数能被 3 3 3整除,那么它的数位之和为一定可以被 3 3 3整除,简单证明一下,设一个 k k k位数,每个位数为 x i x_i xi
n = x k ∗ 1 0 k + x k − 1 ∗ 1 0 k − 1 + . . . x 2 ∗ 10 + x 1 ( x k + x k − 1 + . . x 2 + x 1 ) m o d    3 = 0 n m o d    3 = ∑ i = 1 k ( ( x i m o d    3 ) ∗ ( 1 0 i m o d    3 ) ) = ∑ i = 1 k ( x i m o d    3 ) = 0 n=x_k*10^k+x_{k-1}*10^{k-1}+...x2*10+x_1\\ (x_k+x_{k-1}+..x_2+x_1)\mod 3=0\\ n\mod3=\sum_{i=1}^{k}((x_i\mod 3)*(10^i\mod 3))=\sum_{i=1}^{k}(x_i\mod 3)=0 n=xk10k+xk110k1+...x210+x1(xk+xk1+..x2+x1)mod3=0nmod3=i=1k((ximod3)(10imod3))=i=1k(ximod3)=0
同理可以得出,一个数能被 9 9 9整除,那么它的数位之和一定能被 9 9 9整除

一个数能被 5 5 5整除,它的末尾一定是 0 0 0 5 5 5

最后是 7 7 7有点麻烦,得找找规律,发现题中 n = 111..111 ∗ d n=111..111*d n=111..111d,由 1 1 1构成的 n n n中最小的能被 7 7 7整除的为 111111 111111 111111

所以只要 n ! m o d    6 = = 0 n!\mod6==0 n!mod6==0 n > = 3 n>=3 n>=3 n n n一定可以表示为 111111 ∗ a + 111111 ∗ b + . . . 111111*a+111111*b+... 111111a+111111b+...

#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10;
map<int,int>mp;
int n;int a[N];
int l[N],r[N];
long long gcd(long long a,long long b)
{
	return b? gcd(b,a%b):a;
}
void solve()
{
	int n,d;cin>>n>>d;
	cout<<"1 ";
	if(n>=3||d%3==0)cout<<"3 ";
	if(d==5)cout<<"5 ";
	if(n>=3||d==7)cout<<"7 ";
	if(n>=6||(n>=3&&d%3==0)||d==9)cout<<"9 ";
	cout<<endl;
}
int main()
{
	int t;cin>>t;
	while(t--)solve();
}

Problem - C - Codeforces

dp 数学

给出一个整数数组,数组最多有一个数 x x x不是 − 1 , 1 -1,1 1,1

问数组的一个连续段的和最多有几种不同结果,考虑空段

观察题目显然想到要把数组分为 x x x左边和 x x x右边,独立来看

对于一个只有 − 1 , 1 -1,1 1,1的序列,假设它的连续段和最大为 x x x,最小为 y y y,可以证明它的连续段和肯定可以取满 [ y , x ] [y,x] [y,x]内的值

证明:对于最大值 x x x,由于它是由一个连续段相加得来,那么肯定可以将这个连续段分为若干个和为 1 1 1的更小的段,从两端开始移去子段,得到的连续段和为 x − 1 , x − 2...0 x-1,x-2...0 x1,x2...0,所以肯定可以取满 [ 0 , x ] [0,x] [0,x],同理可得取满 [ y , 0 ] [y,0] [y,0]

对于求最大最小值就是简单的 d p dp dp问题了

设已经求出的左边范围是 [ a , b ] [a,b] [a,b],右边为 [ c , d ] [c,d] [c,d],(由于肯定包含 0 0 0,两者肯定有交集)将其合并为 [ x , y ] [x,y] [x,y],那么答案至少是 y − x + 1 y-x+1 yx+1

再考虑 x x x,设它的坐标是 i n d ind ind,只用求出 [ i n d + 1 , n ] [ind+1,n] [ind+1,n]的前缀和与 [ 1 , i n d − 1 ] [1,ind-1] [1,ind1]的后缀和,将他们的范围(最大值大于等于 0 0 0,最小值小于等于 0 0 0)相加得到 [ x 1 , y 1 ] [x_1,y_1] [x1,y1]

遍历这个区间加上 x x x看看有没有新的值加入即可

#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10;
map<int,int>mp;
int n;int a[N];
int l[N],r[N];
void solve()
{
	mp.clear();int ind=-1;int ans=0;
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		l[i]=r[i]=0;
		scanf("%d",&a[i]);
		if(a[i]<-1||a[i]>1||a[i]==0)ind=i;
	}
	int aa=0,b=0,c=0,d=0;
	if(ind==-1)ind=n+1;
	for(int i=1;i<ind;i++)
	{
		l[i]=max(a[i],l[i-1]+a[i]);
		r[i]=min(a[i],r[i-1]+a[i]);
		aa=max(aa,l[i]);
		b=min(b,r[i]);
	}
	for(int i=ind+1;i<=n;i++)
	{
		l[i]=max(a[i],l[i-1]+a[i]);
		r[i]=min(a[i],r[i-1]+a[i]);
		c=max(c,l[i]);
		d=min(d,r[i]);
	}
	b=min(b,d);aa=max(aa,c);ans=aa-b+1;
	for(int i=b;i<=aa;i++)mp[i]++;
	if(ind!=n+1)
	{
		if(!mp[a[ind]])
		{
			mp[a[ind]]++;
			ans++;
		}
		int sum=0;
		int x1=0,x2=0,y1=0,y2=0;
		for(int i=ind+1;i<=n;i++)
		{
			sum+=a[i];x1=min(x1,sum);x2=max(x2,sum);
		}
		sum=0;
		for(int i=ind-1;i;i--)
		{
			sum+=a[i];y1=min(y1,sum);y2=max(y2,sum);
		}
		int ll=x1+y1,rr=x2+y2;
		for(int i=ll;i<=rr;i++)
		{
			if(!mp[a[ind]+i])
			{
				mp[a[ind]+i]++;ans++;
			}
		}
	}
	cout<<ans<<endl;
	for(auto x:mp)
	{
		cout<<x.first<<' ';
	}
	cout<<endl;
}
int main()
{
	int t;cin>>t;
	while(t--)solve();
}

Problem - D - Codeforces

质数 数学

给出 l , r , g l,r,g l,r,g,求 l ≤ a ≤ b ≤ r , g c d ( a , b ) = g l\leq a\leq b \leq r ,gcd(a,b)=g labr,gcd(a,b)=g的,满足 ∣ a − b ∣ |a-b| ab最大的 a , b a,b a,b

模板题,需要一个转化,对于 x = g ∗ a   , y = g ∗ b x=g*a\ , y=g*b x=ga ,y=gb,如果 g c d ( x , y ) = g gcd(x,y)=g gcd(x,y)=g,那么一定有 g c d ( a , b ) = 1 gcd(a,b)=1 gcd(a,b)=1

那么题目就转化为了找到 [ ( l + g − 1 ) / g , r / g ] [(l+g-1)/g,r/g] [(l+g1)/g,r/g]之间的最大互质对

要根据质数的性质,在题目给的 1 0 18 10^{18} 1018的范围下,相邻质数的距离最大不会超过 1500 1500 1500

其实,设 g n g_n gn为在小于等于 n n n的范围内相邻质数的最大距离, g 1 0 18 = 1442 g_{10^{18}}=1442 g1018=1442

考虑 l l l的下一个质数为 q q q,考虑 r r r的上一个质数为 p p p,两个不相等的质数一定互质,所以答案最坏也要是 ( q , p ) (q,p) (q,p)

在最差的情况下要遍历 g n 2 ∗ l g ( r ) g_n^2*lg(r) gn2lg(r),时间是足够的

从大到小枚举长度即可,看似时间复杂度是 n 2 n^2 n2,,其实很快就可以在两端找到答案

#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10;
map<int,int>mp;
int n;int a[N];
int l[N],r[N];
long long gcd(long long a,long long b)
{
	return b? gcd(b,a%b):a;
}
void solve()
{
	long long x,y,g;cin>>x>>y>>g;
	long long l=(x+g-1)/g,r=y/g;
	for(long long len=r-l;len>=0;len--)
	{
		for(long long i=l;i+len<=r;i++)
		{
			if(gcd(i,i+len)==1)
			{
				cout<<g*i<<' '<<g*(i+len)<<endl;return ;
			}
		}
	}
	cout<<"-1 -1"<<endl;
}
int main()
{
	int t;cin>>t;
	while(t--)solve();
}

可以得到求 [ l , r ] [l,r] [l,r]内的最大互质对的模板

void getprime(long long a, long long b)
{
    for(long long len=r-l;len>=0;len--)
	{
		for(long long i=l;i+len<=r;i++)
		{
			if(gcd(i,i+len)==1)
			{
				cout<<i<<' '<<i+len<<endl;return ;
			}
		}
	}
}

网站公告

今日签到

点亮在社区的每一天
去签到