2020.5.18训练赛

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;
}

猜你喜欢

转载自blog.csdn.net/qq_42937838/article/details/106206530