Codeforces Round #641 div2

Codeforces Round #641 div·2

A - Orac and Factors

题意:

给你一个 n 和 k ,每次让n加上它最小的因子(1除外),不断加k次

解题思路:

对于偶数,必定是这个数加上 2 * k;

对于奇数,它的第一个因子必定是奇数,然后相加变成偶数,然后就再加上(k-1)*2即可

 1 #include<bits/stdc++.h>
 2 #define mem(a) memset(a,0,sizeof(a))
 3 #define forn(i,n) for(int i=0;i<n;++i)
 4 #define for1(i,n) for(int i=1;i<=n;++i)
 5 #define IO std::ios::sync_with_stdio(false); std::cin.tie(0)
 6 #define ll long long
 7 #define inf 0x3f3f3f3f
 8 #define lowbit(x) x&(-x)
 9 using namespace std;
10 const int maxn=1e6+5;
11 ll n,a,b,c,t,k;
12 
13 
14 int main()
15 {
16     IO;
17     cin>>t;
18     while(t--)
19     {
20         cin>>n>>k;
21         a=sqrt(n)+1;
22         if(n%2==0)
23         {
24             n+=k*2;
25         }
26         else
27         {
28             for(int i=3; i<=n; i=i+2)
29             {
30                 if(n%i==0)
31                 {
32                     n+=i;
33                     k--;
34                     break;
35                 }
36             }
37             n+=k*2;
38         }
39         cout<<n<<endl;
40     }
41     return 0;
42 }

 

B - Orac and Models

 题意:

就是让你找最长的递增序列,同时这个序列中每两个相邻的数字在原序列中的下标能够使前面的下标整除后面的下标

解题思路:

这道题只要dp一遍,对于每一个 i ,它只被它的因子的数字影响,所以我们只需要考虑它的因子是否比它小就行了

而我们可以知道,对于 i ,它的所有因子的一半都在0 - sqrt(i)之间,所以整个方法的时间复杂度是 n*sqrt(n)

 1 #include<bits/stdc++.h>
 2 #define mem(a) memset(a,0,sizeof(a))
 3 #define forn(i,n) for(int i=0;i<n;++i)
 4 #define for1(i,n) for(int i=1;i<=n;++i)
 5 #define IO std::ios::sync_with_stdio(false); std::cin.tie(0)
 6 #define ll long long
 7 #define inf 0x3f3f3f3f
 8 #define lowbit(x) x&(-x)
 9 using namespace std;
10 const int maxn=1e5+5;
11 ll n,b,c,t,k;
12 int a[maxn];
13 int dp[maxn];
14 
15 int main()
16 {
17     IO;
18     cin>>t;
19     while(t--)
20     {
21         cin>>n;
22         for1(i,n)
23         {
24             cin>>a[i];
25             dp[i]=1;
26         }
27 
28         int ans=1;
29         for(int i=2;i<=n;++i)
30         {
31             if(a[i]>a[1])
32                 dp[i]=max(dp[i],dp[1]+1);
33             for(int j=2;j*j<=i;++j)
34             {
35                 if(i%j==0)
36                 {
37                     if(a[i]>a[j])
38                         dp[i]=max(dp[i],dp[j]+1);
39                     if(a[i]>a[i/j])
40                         dp[i]=max(dp[i],dp[i/j]+1);
41                 }
42             }
43             ans=max(dp[i],ans);
44         }
45         cout<<ans<<endl;
46     }
47     return 0;
48 }

 

C - Orac and LCM

题意:

找到n个数最小公倍数之间的最大公约数

t={lcm(ai,aj|i<j)} 输出gcd(t)

解题思路:

我们对于每一个数都进行处理,来将它因式分解;而对于我们的最终结果,它的因子应该是至少有n-1个数都有的因子

所以,我们只要记录因子的情况,然后去寻找里面个数大于n-1的数,将他乘到我们的结果里面去,那么最终得到的答案就是我们想要的答案

PS:思路没问题,但是我被卡了很久,因为有一组特殊的数据,可能是全是在范围之内的最大的质数,于是我最后对于ai是质数的情况进行了特判,就过了!!!

#include<bits/stdc++.h>
#define mem(a) memset(a,0,sizeof(a))
#define forn(i,n) for(int i=0;i<n;++i)
#define for1(i,n) for(int i=1;i<=n;++i)
#define IO std::ios::sync_with_stdio(false); std::cin.tie(0)
#define ll long long
#define inf 0x3f3f3f3f
#define lowbit(x) x&(-x)
using namespace std;
const int maxn=3e5+5;
ll n,b,c,t,k,tot;
int prime[maxn];
int cnt[maxn][19];
int met[maxn];
bool vis[maxn];

bool isprime(int x)
{
    for(int i=2; i*i<=x; ++i)
    {
        if(x%i==0)
            return false;
    }
    return true;
}

void init()
{
    k=0;
    for(int i=2; i<=3e5; ++i)
    {
        if(isprime(i))
            prime[k++]=i;
    }
}

int main()
{
    IO;
    init();
    while(cin>>n)
    {
        mem(cnt);
        mem(vis);
        tot=0;
        forn(s,n)
        {
            cin>>b;
            if(isprime(b))
            {
                if(!vis[b])
                {
                    met[tot++]=b;
                    vis[b]=true;
                }
                cnt[b][1]++;
                continue;
            }
            for(int i=0; prime[i]<=b; ++i)
            {
                int tmp=0;
                while(b%prime[i]==0)
                {
                    if(!vis[prime[i]])
                    {
                        met[tot++]=prime[i];
                        vis[prime[i]]=true;
                    }
                    b/=prime[i];
                    tmp++;
                }
                //cout<<prime[i]<<" "<<tmp<<endl;
                for(int q=1; q<=tmp; ++q)
                {
                    cnt[prime[i]][q]++;
                }
            }
        }

        ll ans=1;
        for(int i=0; i<tot; ++i)
        {
            //cout<<met[i]<<endl;
            for(int j=1; j<=18; ++j)
            {
                if(cnt[met[i]][j]<n-1)
                    break;
                if(cnt[met[i]][j]>=n-1)
                    ans*=met[i];
            }
        }
        cout<<ans<<endl;
    }
    return 0;
}

 

后三篇明天再做哦耶!

t={lcm({ai,aj}) | i<j}

posted @ 2020-05-13 20:42  小松QAQ  阅读(171)  评论(0编辑  收藏  举报