Codeforces Round #641 (Div. 2)A~E题解(数论场)

在这里插入图片描述
题目大意就是给你一个数执行k次操作,每次加上这个数的最小质因子(除了一以外)变成一个新的数,问最后的数是多少
解题思路:很明显如果一开始是偶数的话就会一直加2加2,如果是奇数的话先找到这个数的质因子一定是奇数,奇数加奇数就会变成偶数再重复上述过程
下面看代码

#include <iostream>
#include <cstdio>
#include <stack>
#include <sstream>
#include <vector>
#include <map>
#include <cstring>
#include <deque>
#include <cmath>
#include <deque>
#include <iomanip>
#include <queue>
#include <algorithm>
#include <set>
#define mid ((l + r) >> 1) 
#define Lson rt << 1, l , mid
#define Rson rt << 1|1, mid + 1, r
#define ms(a,al) memset(a,al,sizeof(a))
#define _for(i,a,b) for( int i = (a); i < (b); ++i)
#define _rep(i,a,b) for( int i = (a); i <= (b); ++i)
#define for_(i,a,b) for( int i = (a); i >= (b); -- i)
#define rep_(i,a,b) for( int i = (a); i > (b); -- i)
#define lowbit(x) ((-x) & x)
#define IOS std::ios::sync_with_stdio(0); cin.tie(0); cout.tie(0)
#define INF 0x3f3f3f3f
#define hash Hash
#define pb(a) push_back(a)
#define all(x) x.begin(),x.end()
#define next Next
#define f first
#define s second
using namespace std;
const int N = 2e5 + 10;
const double eps = 1e-9;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int> PII;
inline LL read() {
   LL s=0,w=1;
   char ch=getchar();
   while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
   while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
   return s*w;
}

LL fact(LL n)
{
    _for(i,2,n+1)
      if(n % i == 0) return i;
    
    return n;
}

int main()
{
    int T;
    cin >> T;
    while(T --)
    {
        LL n, k;
        cin >> n >> k;
        if(n % 2 == 0)
            cout << n + k * 2 << endl;
        else 
           cout << n + fact(n) + (k - 1) * 2 << endl;
    }
    return 0;
}

B. Orac and Models
在这里插入图片描述
题目大意:给你一个序列,让你求相邻下标是整数倍,的最长上升之序列的长度
解题思路:我们可以先预处理出每个数的因子,再去跑一遍dp[i]是以这个数结尾的最长上升子序列的长度
下面看代码

#include <iostream>
#include <cstdio>
#include <stack>
#include <sstream>
#include <vector>
#include <map>
#include <cstring>
#include <deque>
#include <cmath>
#include <deque>
#include <iomanip>
#include <queue>
#include <algorithm>
#include <set>
#define mid ((l + r) >> 1) 
#define Lson rt << 1, l , mid
#define Rson rt << 1|1, mid + 1, r
#define ms(a,al) memset(a,al,sizeof(a))
#define _for(i,a,b) for( int i = (a); i < (b); ++i)
#define _rep(i,a,b) for( int i = (a); i <= (b); ++i)
#define for_(i,a,b) for( int i = (a); i >= (b); -- i)
#define rep_(i,a,b) for( int i = (a); i > (b); -- i)
#define lowbit(x) ((-x) & x)
#define IOS std::ios::sync_with_stdio(0); cin.tie(0); cout.tie(0)
#define INF 0x3f3f3f3f
#define hash Hash
#define pb(a) push_back(a)
#define all(x) x.begin(),x.end()
#define next Next
#define f first
#define s second
using namespace std;
const int N = 2e5 + 10;
const double eps = 1e-9;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int> PII;
inline LL read() {
   LL s=0,w=1;
   char ch=getchar();
   while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
   while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
   return s*w;
}
int a[N];
int dp[N];
vector<int> fact[N];
int main()
{
    int T;
    cin >> T;
   for(int i = 1; i <= 100010; ++ i)
        for(int j = i; j <= 100010;j += i)
            fact[j].push_back(i);
    while(T --)
    {
        int n;
        cin >> n;
        ms(dp,0);
        _for(i,1,n+1) cin >> a[i];
        int ans = 0;
        _for(i,1,n+1)
        {
          dp[i] = 1;
          for(auto it : fact[i])
           if(a[i] > a[it] && it != i)
               dp[i] = max(dp[it] + 1,dp[i]);
           
           ans = max(dp[i],ans);
        }
        cout << ans << endl;
    }
    return 0;
}

C. Orac and LCM
在这里插入图片描述
题目大意:就是给你一串序列,然后将这些数两两配对LCM形成新的序列,求这个序列的GCD
解题思路:我们可以手动模拟一下gcd里面一定是原序列里面的质因子构成的对于gcd中的某一个质数p其指数一定是原序列数中指数第二小的数,那么我们就可以把每个数分解质因数的情况存起来。接下来我们就要算每个质因子的贡献,当且仅当包含这个质因子数的个数>=n-1是有效的(因为它要和别的数配对)
解法2:lcm就是p1^max(k1,k2), gcd就是p1 ^ min(k1,k2)
在这里插入图片描述
lcm a,x是a和x质因子的并集
同理 lcm a,y是a和y质因子的并集
二者的交集就是a与x交y的并集
通俗考虑的话 lcm a,y是在a的基础上增加了y的质因子
同理那边多了x的质因子
取gcd以后,a的质因子是肯定全部存在的
剩下的取x与y的质因子的公共部分

下次不能用pow了qwq(wa到挂机)

#include <iostream>
#include <cstdio>
#include <stack>
#include <sstream>
#include <vector>
#include <map>
#include <cstring>
#include <deque>
#include <cmath>
#include <deque>
#include <iomanip>
#include <queue>
#include <algorithm>
#include <set>
#define mid ((l + r) >> 1) 
#define Lson rt << 1, l , mid
#define Rson rt << 1|1, mid + 1, r
#define ms(a,al) memset(a,al,sizeof(a))
#define _for(i,a,b) for( int i = (a); i < (b); ++i)
#define _rep(i,a,b) for( int i = (a); i <= (b); ++i)
#define for_(i,a,b) for( int i = (a); i >= (b); -- i)
#define rep_(i,a,b) for( int i = (a); i > (b); -- i)
#define lowbit(x) ((-x) & x)
#define IOS std::ios::sync_with_stdio(0); cin.tie(0); cout.tie(0)
#define INF 0x3f3f3f3f
#define hash Hash
#define pb(a) push_back(a)
#define all(x) x.begin(),x.end()
#define next Next
#define f first
#define s second
using namespace std;
const int N = 2e5 + 10;
const double eps = 1e-9;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int> PII;
inline LL read() {
   LL s=0,w=1;
   char ch=getchar();
   while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
   while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
   return s*w;
}
vector <int> e[N];

LL qmi(LL a, LL b)
{
    LL res = 1;
    while(b)
    {
        if(b & 1) res = res * a;
        b >>= 1;
        a = a * a;
    }
    return res;
}
int main()
{
    int n;
    cin >> n;
    _for(j,0,n)
    {
        LL x;
        cin >> x;
        _for(i,2,sqrt(x)+1)
        {
            if(x % i == 0)
            {
                LL cnt = 0;
                while(x % i == 0)
                {
                  x /= i;
                  ++ cnt;
                }
                e[i].push_back(cnt);
            }
        }
       if(x != 1) e[x].push_back(1);
    }
    
    LL ans = 1;
    for(int it = 1; it <= N - 1; ++ it)
      if(e[it].size() >= n - 1)
      {
          sort(e[it].begin(),e[it].end());
          if(e[it].size() == n) ans *= (LL)qmi(it,e[it][1]);
          else ans *= (LL)qmi(it,e[it][0]);
      }
    cout << ans << endl;
    return 0;
}

D. Orac and Medians
在这里插入图片描述
题目大意:就是给你一个长度为n的序列你可以挑选一个l到r区间,把l到r区间内的数全部都变成这个区间的中位数,问你最后是否可以把整个序列都变成数字k
解题思路:1很明显如果这个序列都没有k那么根本就不仅可能
2.如果k旁边有大于k数那么就可以把所有的数全部都变成k,
举个例子我们先取k和大于k这两个数那么我们就可以把这两个数全都变成k
3.如果某个区间内大于等于k的数量大过一半那么这个区间就可以全部变成大于等于k的数
综上所述,我们只要判断一下第一和第3个条件是否成立就可以了。
如何判断第3个成立呢?对于一段区间内如果>=k的数量过半那么一定有一对大于等于k的数间隔小于等于2


#include <iostream>
#include <cstdio>
#include <stack>
#include <sstream>
#include <vector>
#include <map>
#include <cstring>
#include <deque>
#include <cmath>
#include <deque>
#include <iomanip>
#include <queue>
#include <algorithm>
#include <set>
#define mid ((l + r) >> 1) 
#define Lson rt << 1, l , mid
#define Rson rt << 1|1, mid + 1, r
#define ms(a,al) memset(a,al,sizeof(a))
#define _for(i,a,b) for( int i = (a); i < (b); ++i)
#define _rep(i,a,b) for( int i = (a); i <= (b); ++i)
#define for_(i,a,b) for( int i = (a); i >= (b); -- i)
#define rep_(i,a,b) for( int i = (a); i > (b); -- i)
#define lowbit(x) ((-x) & x)
#define IOS std::ios::sync_with_stdio(0); cin.tie(0); cout.tie(0)
#define INF 0x3f3f3f3f
#define hash Hash
#define pb(a) push_back(a)
#define all(x) x.begin(),x.end()
#define next Next
#define f first
#define s second
using namespace std;
const int N = 2e5 + 10;
const double eps = 1e-9;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int> PII;
inline LL read() {
   LL s=0,w=1;
   char ch=getchar();
   while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
   while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
   return s*w;
}
int e[N];
int main()
{
    int T;
    cin >> T;
    while(T --)
    {
        int n, k;
        cin >> n >> k;
        bool flag = false;
        _for(i,1,n+1) 
        {
            cin >> e[i];
            if(e[i] > k) e[i] = 1;
            else if(e[i] == k) e[i] = 0, flag = true;
            else e[i] = -1;
        }
        if(n == 1 && flag == true)
        {
            cout << "yes" << endl;
            continue;
        }
        if(!flag) 
        {
            cout << "no" << endl;
            continue;
        }
        flag = false;
        _for(i,1,n)
          if(e[i] >= 0 && e[i + 1] >= 0) 
          {
              flag = true;
              break;
          }
         
        _for(i,1,n-1)
          if(e[i] >= 0 && e[i + 2] >= 0)
          {
              flag = true;
              break;
          }
         if(!flag)
           cout << "no" << endl;
          else cout << "yes" << endl;
    } 
    return 0;
}

E. Orac and Game of Life
在这里插入图片描述
题目大意就说:给你一个n*m的矩阵,里面是0或者1,对于一个0或者1如果它旁边又跟它相同的数字那么下一秒它们就会变(如果是0就变1,1就变0),有q次询问每次给你一个坐标x,y,和时间t,问你t秒时这个位置上的数是多少
解题思路:我们可以求出每个点第一次翻转的时间是多少(bfs)最短路径算法如果询问的t和第一次激活的时间相差是偶数的话那么就是原来的数字否则就说异或1

不知道为甚d数组要开longlong

#include <iostream>
#include <cstdio>
#include <stack>
#include <sstream>
#include <vector>
#include <map>
#include <cstring>
#include <deque>
#include <cmath>
#include <deque>
#include <iomanip>
#include <queue>
#include <algorithm>
#include <set>
#define mid ((l + r) >> 1) 
#define Lson rt << 1, l , mid
#define Rson rt << 1|1, mid + 1, r
#define ms(a,al) memset(a,al,sizeof(a))
#define _for(i,a,b) for( int i = (a); i < (b); ++i)
#define _rep(i,a,b) for( int i = (a); i <= (b); ++i)
#define for_(i,a,b) for( int i = (a); i >= (b); -- i)
#define rep_(i,a,b) for( int i = (a); i > (b); -- i)
#define lowbit(x) ((-x) & x)
#define IOS std::ios::sync_with_stdio(0); cin.tie(0); cout.tie(0)
#define INF 0x3f3f3f3f
#define hash Hash
#define pb(a) push_back(a)
#define all(x) x.begin(),x.end()
#define next Next
#define f first
#define s second
using namespace std;
const int N = 2e5 + 10;
const double eps = 1e-9;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int> PII;
inline LL read() {
   LL s=0,w=1;
   char ch=getchar();
   while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
   while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
   return s*w;
}
const LL LNF = 8e18;
LL d[1010][1010];
int g[1010][1010];
char G[1010][1010];
LL n, m, k;
int dx[4] = {0,-1,0,1};
int dy[4] = {1,0,-1,0};
void bfs()
{
    queue<PII> q;
    
    _for(i,0,n)
     _for(j,0,m)
      _for(k,0,4)
         {
               int x = i + dx[k], y = j + dy[k]; 
               if(x >= n || y >= m || y < 0 || x < 0) continue;
               if(g[x][y] == g[i][j])
               {
                  q.push({x,y});
                 d[x][y] = 0;
               }
         }
     
    while(!q.empty())
    {
        auto top = q.front();
        q.pop();
        _for(i,0,4)
        {
            int x = top.f + dx[i], y = top.s + dy[i];
            if(x >= n || y >= m || y < 0 || x < 0) continue;
            if(d[x][y] != LNF) continue;
            d[x][y] = d[top.f][top.s] + 1;
            q.push({x,y});
        }
    }
}

int main()
{
  _for(i,0,1005)
   _for(j,0,1005)
    d[i][j] = LNF;
    
    cin >> n >> m >> k;
    
    _for(i,0,n)
    cin >> G[i];
      
    _for(i,0,n)
     _for(j,0,m)
      g[i][j] = G[i][j] - '0';
      
    bfs();
    
    // _for(i,0,n)
    //  _for(j,0,m)
    //   if(j == m - 1)
    //     cout << d[i][j] << endl;
    //   else cout << d[i][j] << " ";
    
    while(k --)
    {
        LL x, y ,j;
        cin >> x >> y >> j;
        -- x, -- y;
        
        if(d[x][y] >= j || (j - d[x][y]) % 2 == 0)
          cout << g[x][y] << endl;
        else cout << (1 ^ g[x][y])   << endl; 
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值