Codeforces Round #641 (Div. 2) A-E

A. Orac and Factors

题意:定义 f [ n ] f[n] f[n] = n n n的最小因数,有q次操作,每次操作让n加上 f [ n ] f[n] f[n],问q次操作后n的值为多少。
思路:

  • 对于偶数来说,输出 n + q ∗ 2 n+q*2 n+q2
  • 对于奇数来说,找到最小因数(必然是个奇数),然后加上这个奇数之后,n就会变成偶数,然后就是偶数的情况了。
#include<bits/stdc++.h>
#define ll long long
#define mk make_pair
#define pi pair<int,int>
#define pb push_back
#define pp pop_back
using namespace std;
 
int main()
{
    
    
	int T;
	cin >> T;
	while(T--)
	{
    
    
		ll n,k;
		cin >> n >> k;
		ll tmp = n;
		if(n%2 == 0)
		{
    
    
			cout<<n+2*k<<'\n';
			continue;
		}
		for(int i=2;i*i<=n;i++)
		{
    
    
			if(n%i==0)
			{
    
    
				tmp = i;
				break;
			}
		}
		if(n&1)
		{
    
    
			n+=tmp;
			k--;
		}
		cout<<n+2*k<<'\n';
	}
	return 0;
}

B. Orac and Models

题意:求带条件的最长上升子序列,条件是: i < j i<j i<j && a [ i ] < a [ j ] a[i] < a[j] a[i]<a[j] && j j j i i i的倍数。
题解:设 d p [ i ] dp[i] dp[i]为包括 i i i在内的最长合法上升子序列,那么 d p [ i ] dp[i] dp[i]肯定是由 d p [ j ] dp[j] dp[j] j < i j<i j<i && i i i j j j的倍数)转移,枚举一下 j j j即可。比 i i i小的数的dp值一定在 i i i直接求出来了。时间复杂度是o( n n n* n \sqrt n n )。

#include<bits/stdc++.h>
#define ll long long
#define mk make_pair
#define pi pair<int,int>
#define pb push_back
#define pp pop_back
using namespace std;
const int maxn = 1e5+100;
int a[100005],dp[100005];
int main()
{
    
    
	int T;
	cin >> T;
	while(T--)
	{
    
    
		int n;
		cin >> n;
		for(int i=1;i<=n;i++)cin>>a[i];
		
		for(int i=1;i<=n;i++)
		{
    
    
			dp[i] = 1;
			for(int j=1;j<=sqrt(i);j++)
			{
    
    
				if(i%j == 0)
				{
    
    
					if(a[i] > a[j])dp[i] = max(dp[i],dp[j] + 1);
				}
				if(i%(i/j) == 0)
				{
    
    
					if(a[i] > a[i/j])dp[i] = max(dp[i],dp[i/j]+1);
				}
			}
		}
		int ans = 0;
		for(int i=1;i<=n;i++)ans = max(ans,dp[i]);
//		cout<<dp[i]<<' ';
//		puts("");
		cout<<ans<<'\n';
	}
	return 0;
}

C. Orac and LCM

题意:给你一个数组,问这个数组中满足 i < j i<j i<j的数对的 l c m lcm lcm组成新的数组 的gcd是多少。
思路:

  • 首先:对于新组成的数组的每一项我们都可以写出 l c m ( a [ i ] , a [ j ] ) lcm(a[i],a[j]) lcm(a[i],a[j]) = a [ i ] ∗ a [ j ] g c d ( a [ i ] , a [ j ] ) \frac{a[i]*a[j]}{gcd(a[i],a[j])} gcd(a[i],a[j])a[i]a[j]

  • i i i等于 1 1 1时,j可取2~n,我们可以推导公式:
    g c d gcd gcd a [ 1 ] ∗ a [ 2 ] g c d ( a [ 1 ] , a [ 2 ] ) \frac{a[1]*a[2]}{gcd(a[1],a[2])} gcd(a[1],a[2])a[1]a[2] a [ 1 ] ∗ a [ 3 ] g c d ( a [ 1 ] , a [ 3 ] ) \frac{a[1]*a[3]}{gcd(a[1],a[3])} gcd(a[1],a[3])a[1]a[3],…)= a [ 1 ] a[1] a[1] * gcd( a [ 2 ] g c d ( a [ 1 ] , a [ 2 ] ) \frac{a[2]}{gcd(a[1],a[2])} gcd(a[1],a[2])a[2] a [ 3 ] g c d ( a [ 1 ] , a [ 3 ] ) \frac{a[3]}{gcd(a[1],a[3])} gcd(a[1],a[3])a[3],…) = a [ 1 ] a[1] a[1] * g c d ( a [ 2 ] ,   . . . . ) g c d ( a [ 1 ] , a [ 2 ] ,   . . . . ) \frac{ {gcd(a[2],\ ....)}}{gcd(a[1],a[2],\ ....)} gcd(a[1],a[2], ....)gcd(a[2], ....) = a [ 1 ]   ∗   g c d ( a [ 2 ] ,   . . . . ) g c d ( a [ 1 ]   ,   g c d ( a [ 2 ] ,   . . . . ) ) \frac{ {a[1] \ *\ gcd(a[2],\ ....)}}{gcd(a[1] \ , \ gcd(a[2],\ ....))} gcd(a[1] , gcd(a[2], ....))a[1]  gcd(a[2], ....) = l c m ( a [ 1 ] , g c d ( a [ 2 ] . . . . . ) lcm(a[1],gcd(a[2].....) lcm(a[1],gcd(a[2].....);

  • 对于所有的数来说,设 p [ i ] p[i] p[i]等于 a [ i ] a[i] a[i]乘以位于 i i i后面的数的gcd,那么答案就是p数组的gcd,这个数后面的gcd,可以像前缀和一样预处理,也可以线段树。

#include<bits/stdc++.h>
#define ll long long
#define mk make_pair
#define pi pair<int,int>
#define pb push_back
#define pp pop_back
using namespace std;
 
const int maxn = 1e5+10;
 
int tr[maxn * 4],a[maxn];
#define ls o<<1
#define rs o<<1|1
#define mid (l+r)/2
 
void up(int o,int l,int r,int p,int val)
{
    
    
	if(l == r)
	{
    
    
		tr[o] += val;
		return ;
	}
	if(p <= mid)up(ls,l,mid,p,val);
	else up(rs,mid+1,r,p,val);
	tr[o] = __gcd(tr[ls],tr[rs]);
}
 
int qu(int o,int l,int r,int L,int R)
{
    
    
	if(l>=L && r<=R)return tr[o];
	if(R <= mid)return qu(ls,l,mid,L,R);
	else if(L > mid)return qu(rs,mid+1,r,L,R);
	else return __gcd(qu(ls,l,mid,L,R),qu(rs,mid+1,r,L,R));
}
int main()
{
    
    
	int n;
	cin >> n;
	for(int i=1;i<=n;i++)
	{
    
    
		cin >> a[i];
		up(1,1,n,i,a[i]);
	}
	ll ans = 1000000009;
	int tmp;
	for(int i=1;i<n;i++)
	{
    
    
		if(i == 1)
		{
    
    
			tmp = qu(1,1,n,i+1,n);
			ans = 1ll*tmp*a[i]/__gcd(tmp,a[i]);
		}
		else 
		{
    
    
			tmp = qu(1,1,n,i+1,n);
			ans = __gcd(ans,1ll*tmp*a[i]/__gcd(tmp,a[i]));
		}	
	}
	cout<<ans<<'\n';
	return 0;
}

D. Orac and Medians

题意:给你一个数组,你可以对这个数组进行有限次操作,使得这个数组中所有的元素的值都等于k,这个操作定义如下,我们可以任意选择一个区间,把这个区间的数都变成他的中位数(如果这个区间长度为偶数,中间偏小的那个数)。如果能全部变成k输出yes,否则输出no。
思路:通过观察我们可以得到结论

  • n = 1 n=1 n=1时,答案取决于 a [ 1 ] = = k ? a[1]==k? a[1]==k?;
  • n ! = 1 n!=1 n=1时 && 数组没有 k k k,输出 n o no no
  • n ! = 1 n!=1 n!=1 && 数组中有k时,如果数组中存在两个连续的大于k的数,输出yes;或者,存在数组中某个数左右两边的数都大于k时,输出yes;
  • 其他情况都是no;
#include<bits/stdc++.h>
#define ll long long
#define mk make_pair
#define pi pair<int,int>
#define pb push_back
#define pp pop_back
using namespace std;
 
int a[100005];
int main()
{
    
    
	int T;
	cin >> T;
	while(T--)
	{
    
    
		int n,k;
		cin >> n >> k;
		int flag = 0,tmp = 0;
		
		for(int i=1;i<=n;i++)
		{
    
    
			cin >> a[i];
			if(n == 1 && a[i] == k)flag = 1;
			if(a[i] == k)tmp = 1;
		}
		
		
		if(!tmp)
		{
    
    
			puts("no");
			continue;
		}
		
		for(int i=2;i<=n;i++) {
    
    
			if(a[i-1]>=k && a[i] >= k)flag = 1;
		}
		for(int i=2;i<n;i++) {
    
    
			if(a[i-1] >= k && a[i+1] >= k)flag = 1;
		}
		
		if(flag)puts("yes");
		else puts("no");
	}
	return 0;
}

E. Orac and Game of Life

题意及题解:连接

#include<bits/stdc++.h>
#define ll long long
#define mk make_pair
#define pi pair<int,int>
#define pb push_back
#define pp pop_back
using namespace std;
 
int a[1005][1005],vis[1005][1005],f[1005][1005];
int x[5] = {
    
    -1,1,0,0};
int y[5] = {
    
    0,0,-1,1};
int n,m,q;
 
bool ok(int xo,int yo)
{
    
    
	for(int i=0;i<4;i++)
	{
    
    
		int tx = xo + x[i];
		int ty = yo + y[i];
		if(tx < 1 || tx > n || ty < 1 || ty > m)continue;
		if(a[xo][yo] == a[tx][ty])return true;
	}
	return false;
}
void bfs()
{
    
    
	queue<pi>q;
	for(int i=1;i<=n;i++)
	for(int j=1;j<=m;j++)
	{
    
    
		if(ok(i,j))
		{
    
    
			q.push(mk(i,j));
			vis[i][j] = 1;
		}
	}
	while(!q.empty())
	{
    
    
		int xo = q.front().first;
		int yo = q.front().second;
		q.pop();
		for(int i=0;i<4;i++)
		{
    
    
			int tx = xo + x[i];
			int ty = yo + y[i];
			if(tx < 1 || tx > n || ty < 1 || ty > m)continue;
			if(vis[tx][ty])continue;
			vis[tx][ty] = 1;
			f[tx][ty] = f[xo][yo] + 1;
			q.push(mk(tx,ty));
		}
	}
}
int main()
{
    
    
	cin >> n >> m >> q;
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)scanf("%1d",&a[i][j]);
	
	bfs();
	
	while(q--)
	{
    
    
		int i,j;
		ll t;
		cin >> i >> j >> t;
		if(vis[i][j])
		{
    
    
			if(t > f[i][j])printf("%d\n",a[i][j] ^ ((t - f[i][j])&1));
			else printf("%d\n",a[i][j]);
		}
		
		else printf("%d\n",a[i][j]);
	
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_44499508/article/details/106117054