https://vjudge.net/contest/374073#overview
A - Orac and Factors CodeForces - 1350A
输入n,k,进行n次n += f(n),其中f(n)为n的最小因数。
可以发现假如n是偶数的话最小因数必为2,并且在进行了一次相加的过程之后也还是偶数,因为偶数加偶数等于偶数。
如果是奇数直接暴力找最小因数就可以了,一旦变成偶数直接输出结果。
//#include<bits/stdc++.h>//poj,hdu can't use it
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <stack>
#include <map>
#include <cmath>
#include <algorithm>
#include <iomanip>
using namespace std;
/************************head file************************/
#define inf 0x3f3f3f3f
#define SI(x) scanf("%d",&x)
#define set0(x) memset(x,0,sizeof(x))
#define ms(x,n) memset(x,n,sizeof(x));
typedef long long ll;
const int mod = 998244353;
const int maxn = 1e5 + 10;
using namespace std;
/***********************defination************************/
int main()
{
int round;
cin>>round;
while(round--)
{
ll n,k,ans;
cin>>n>>k;
ans = n;
while(k){
if(ans % 2 == 0){
ans = ans + 2 * k;break;}
else{
for(ll i = 2;i <= n;i++)
if(ans % i == 0){
ans += i;
break;
}
}
k--;
}
cout<<ans<<endl;
}
return 0;
}
B - Orac and Models CodeForces - 1350B
要求找到一个单向链,要求两相邻下标i,j有j % i == 0,j > i并且sj > si。
很显然是单向的,而且链的下一个可能组成的元素是确定的,为当前下标的倍数,因此利用线性筛的思想就可以确定位置。
找到之后不能用简单的暴力方法加,比如说一个判断条件if(i * num <= k && s[ i ] < s[i * num])ans[*num]++;这样的结果是错误的,因为他是单向传承的,只能选择一个方向。因此正确的做法应该是 ans[i * num] = max(ans[i * num],ans[i] +1);
//#include<bits/stdc++.h>//poj,hdu can't use it
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <stack>
#include <map>
#include <cmath>
#include <algorithm>
#include <iomanip>
using namespace std;
/************************head file************************/
#define inf 0x3f3f3f3f
#define SI(x) scanf("%d",&x)
#define set0(x) memset(x,0,sizeof(x))
#define ms(x,n) memset(x,n,sizeof(x));
typedef long long ll;
const int mod = 998244353;
const int maxn = 100010;
using namespace std;
/***********************defination************************/
ll a[maxn];
int ans[maxn];
int main()
{
int round;
cin>>round;
while(round--)
{
int t;
cin>>t;
for(int i = 1;i <= t;i++)
{
cin>>a[i];
ans[i] = 1;
}
for(int i = 1;i <= t;i++)
for(int j = i*2;j <= t;j += i)
if(a[j] > a[i])
ans[j] = max(ans[j],ans[i] +1);
int m = -inf;
for(int i = 1;i <= t;i++)
m = max(m,ans[i]);
cout<<m<<endl;
}
return 0;
}
C - Orac and LCM CodeForces - 1350C
比赛的之后直接用结论写出来了,现在想一下怎么样推导这个结论。
//#include<bits/stdc++.h>//poj,hdu can't use it
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <stack>
#include <map>
#include <cmath>
#include <algorithm>
#include <iomanip>
using namespace std;
/************************head file************************/
#define inf 0x3f3f3f3f
#define SI(x) scanf("%d",&x)
#define set0(x) memset(x,0,sizeof(x))
#define ms(x,n) memset(x,n,sizeof(x));
typedef long long ll;
const int mod = 998244353;
const int maxn = 100010;
using namespace std;
/***********************defination************************/
ll f[maxn],s[maxn],t[maxn],ans;
ll gcd(ll a,ll b){
return b?gcd(b,a%b):a;
}
ll lcm(ll a,ll b){
return a*b/gcd(a,b);
}
int main()
{
int n,i;
cin>>n;
for(i = 1;i <= n;i++)
cin>>f[i];
s[n] = f[n];
for(i = n-1;i >= 1;i--)s[i]=gcd(s[i+1],f[i]);
for(i = 1;i < n;i++)t[i]=lcm(f[i],s[i+1]);
ans = t[1];
for(i = 2;i < n;i++)ans=gcd(ans,t[i]);
cout<<ans<<endl;
return 0;
}