Codeforces Round #641 (Div. 2)
A. Orac and Factors
题解
当 \(n\) 为偶数时, \(n\) 每次的最小因子(除 \(1\)以外)都是 \(2\)。
当 \(n\) 为奇数时,\(n\) 每次的最小因子(除 \(1\)以外)是奇数,当奇数加上奇数之后为偶数,则后面的 \(k-1\) 次都是\(2\)。
解决的思路:不论是不是奇数,先求解出最小的因子(除 \(1\)以外),再加上 \((k-1)*2\) 。
代码
#include <cmath>
#include <cstdio>
#include <iostream>
using namespace std;
typedef long long ll;
int main(){
int t;
scanf("%d",&t);
while(t--){
ll n,k;
scanf("%lld%lld",&n,&k);
ll m=sqrt(n),res=n,ret=n;
for(ll i=2;i<=m;++i){
if(n%i==0){
ret=i;
break;
}
}
res+=ret;
res+=(k-1)*2;
printf("%lld\n",res);
}
return 0;
}
B. Orac and Models
题解
感觉代码很像筛法,对于任何一个数 \(i\) ,枚举它所有的最倍数,再根据条件 \(a_i<a_j\) 用于求解最大值。
注:初始化的坑很强大。
代码
#include <cstdio>
#include <iostream>
using namespace std;
const int maxn = 1e5+5;
int a[maxn];
int b[maxn];
int max(int x,int y){
return x>y?x:y;
}
int main(){
int t,n;
scanf("%d",&t);
while(t--){
scanf("%d",&n);
for(int i=1;i<=n;++i){
b[i]=1;
scanf("%d",&a[i]);
}
int maxx=1;
for(int i=1;i<=n;++i){
for(int j=i*2;j<=n;j+=i){
if(a[j]>a[i]){
b[j]=max(b[j],b[i]+1);
maxx=max(maxx,b[j]);
}
}
}
printf("%d\n",maxx);
}
return 0;
}
C. Orac and LCM
题解
求解 \(gcd({lcm({ai,aj}) | i<j})\) 最暴力的解法是 枚举所有的 \(i\) 和 \(j\) 来进行求解
for(int i=1;i<n;++i){
for(int j=i+1;j<=n;++j){
res=gcd(res,lcm(a[i],a[j]));
}
}
就像这样,但实际上会超时的。
那么可以采用一些优化措施,
\(gcd({lcm({ai,aj}) | i<j})\) 可以这样理解,
枚举每一个 \(i\) ,使 \(c_i=lcm(a_i,a_j)\) 满足 \(i\) 不变并且 \(j>i\) ,之后计算 \(gcd(c_i)\)
那就是这样
for(int i=1;i<n;++i){
c[i]=a[i];
for(int j=i+1;i<=n;++j){
c[i]=lcm(c[i],a[j]);
}
}
int ret=c[1];
for(int i=2;i<n;++i){
ret=gcd(ret,c[i]);
}
你可能会发现一个规律,\(c_i\) 表示的是 \(a_i\) 和所有 \(a_j\) 的 \(lcm\)
\(namo\) ,提前预处理一下所有的 \(lcm\) 存储到 \(b_i\) 中。
后面的就是计算 \(a_i\) 和 \(b_{i+1}\) 的 \(gcd\) 了。
代码
#include <cmath>
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 1e5+5;
typedef long long ll;
ll gcd(ll a,ll b){return b==0?a:gcd(b,a%b);}
ll a[maxn];
ll b[maxn];
int main(){
int n;
scanf("%d",&n);
for(int i=1;i<=n;++i){
scanf("%d",&a[i]);
b[i]=a[i];
}
for(int i=n-1;i>0;--i){
b[i]=gcd(b[i+1],b[i]);
}
ll ret=a[1]*b[2]/gcd(a[1],b[2]);
for(int i=1;i<n;++i){
ret=gcd(ret,a[i]*b[i+1]/gcd(a[i],b[i+1]));
}
printf("%lld\n",ret);
return 0;
}
D. Orac and Medians
题解
输出 \(yes\) 的一个必要条件是数组中存在 \(k\) ,其次是如果有两个连续的数大于等于 \(k\) 的话,\(namo\) 再加上任何一个小于 \(k\) 的话,这连续的三个数的值 都会大于等于 \(k\) ,此后依次吞噬小的数,当遇到k时,两个大于等于 \(k\) 的数放在一起会变成两个 \(k\) 的。经过这样之后剩下的都是数组可以想象出来都是什么样子的。
最后筛一个 \(a_{i+1},a_{i-1}≥k\) 并且\(ai<k\) 只要满足这种情况就会生成连续三个都大于等于 \(k\) 的数字。
总结一下就是满足下列条件之一就输出 \(yes\)
- 数组中存在 \(k\) 并且满足 \(a_i,a_{i+1}≥k\)
- 数组中存在 \(k\) 并且满足 \(a_{i+1},a_{i-1}≥k,ai<k\)
- \(n=1\) 并且存在 \(k\) (最坑的点)
代码
#include <cmath>
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 1e5+5;
int a[maxn];
int b[maxn]={0};
int main(){
int t;
scanf("%d",&t);
while(t--){
int n,k;
int flag=0,f=0;
scanf("%d%d",&n,&k);
for(int i=1;i<=n;++i){
scanf("%d",&a[i]);
if(a[i]>=k&&a[i-1]>=k&&i!=1)flag=1;
if(a[i]>=k&&a[i-1]<k&&a[i-2]>=k&&i>=2)flag=1;
if(a[i]==k)f=1;
}
if(!f){
printf("no\n");
continue;
}
if(flag||n==1){
printf("yes\n");
continue;
}
printf("no\n");
}
return 0;
}
E. Orac and Game of Life
题解
根据题意它内部的变化是上下左右有相同的则变,否则不进行改变,其次的话如果图中的某一个位置发生了变化,之后它的变化就会是周期性的变化。
现在要解决的问题就会是它什么时候发生变化,发生的变化来自于存在至少两个相等的位置扩散来的变化,就像这样
一遍 \(bfs\) 搜索一下,记录一下到达的时间,输出的时候判断一下规律就好了。
代码
#include <cmath>
#include <queue>
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxn = 1e3+5;
struct node{int x,y;ll val;};
int step[4][2]={{0,1},{0,-1},{1,0},{-1,0}};
char s[maxn][maxn];
int vis[maxn][maxn];
ll dis[maxn][maxn];
int main(){
queue<node>Q;
int n,m,t;
scanf("%d%d%d",&n,&m,&t);
for(int i=0;i<n;++i){
for(int j=0;j<m;++j){
dis[i][j]=1e18+1;
}
}
for(int i=0;i<n;++i)scanf("%s",s[i]);
for(int i=0;i<n;++i){
for(int j=0;j<m;++j){
for(int k=0;k<4;++k){
int x=i+step[k][0];
int y=j+step[k][1];
if(x>=0&&x<n&&y>=0&&y<m&&s[x][y]==s[i][j]){
Q.push({i,j,0});
vis[i][j]=1;
dis[i][j]=0;
break;
}
}
}
}
while(!Q.empty()){
node p=Q.front();
Q.pop();
for(int i=0;i<4;++i){
int x=step[i][0]+p.x;
int y=step[i][1]+p.y;
if(x>=0&&x<n&&y>=0&&y<m&&!vis[x][y]){
// cout<<x<<" "<<y<<" "<<p.x<<" "<<p.y<<endl;
vis[x][y]=1;
dis[x][y]=p.val+1;
Q.push({x,y,dis[x][y]});
}
}
}
// for(int i=0;i<n;++i){
// for(int j=0;j<m;++j)
// cout<<dis[i][j]<<" ";
// cout<<endl;
// }
while(t--){
int x,y;
ll q;
scanf("%d%d%lld",&x,&y,&q);
x--;y--;
int val=s[x][y]-'0';
if(dis[x][y]<=q){
val=((q-dis[x][y])%2+val)%2;
printf("%d\n",val);
}
else printf("%d\n",val);
}
return 0;
}

浙公网安备 33010602011771号