题解2023.5.23(欧拉筛)

C.Hossamand Trainees
 欧拉筛,预处理先筛出质数,分解质因数对于出现两次及以上的输出yes
 我们需要筛出根号(1e9)以内的所有质数,根据质数定理,大约有4e^3个质数,
 时间复杂度分析:le5*4e3=4e8

#include<bits/stdc++.h>
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(fast) 
#include<iostream>
#include<algorithm>
#include<map>
#include<set>
#include<queue>
#include<cstring>
#include<math.h>
#include<map>
#include<vector>
#define ms(x,y) memset(x,y,sizeof x)
#define int long long 
const int maxn = 2e5 + 10, INF = 0x3f3f3f3f;
using namespace std;
int a[maxn];
int cnt = 0;
int st[1000060];
int p[1000060];
void init() {
    for (int i = 2; i < 40000; i++) {
        if (!st[i])
            p[cnt++] = i;
        for (int j = 0; p[j] * i < 40000; j++) {
            st[p[j] * i] = true;
            if (i % p[j] == 0)
                break;
        }
    }
}
void solve() {
    int n;
    cin >> n;
    map<int, int>mp;
    for (int i = 1; i <= n; i++) {
        cin >> a[i];
    }
    for (int i = 1; i <= n; i++) {
        int num = a[i];
        for (int j = 0; p[j] * p[j] <= num; j++) {
            int p1 = p[j];
            if (num % p1 == 0) {
                while (num % p1 == 0) {
                    num /= p1;
                }
                mp[p1]++;
                if (mp[p1] > 1) {
                    cout << "YES" << '\n';
                    return;
                }

            }
        }
        if (num >1)mp[num]++;
        if (mp[num] > 1) {
            cout << "YES" << '\n';
            return;
        }
    }
    cout << "NO" << '\n';
}
signed main()
{
    ios::sync_with_stdio(false);
    init();
    int t;
    cin >> t;
    while (t--) {
        solve();
    }
}


B.Hossamand Friends
 思路:双指针,用一个数组记录右指针可取的最大左边界
 

#include<bits/stdc++.h>
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(fast) 
#include<iostream>
#include<algorithm>
#include<map>
#include<set>
#include<queue>
#include<cstring>
#include<math.h>
#include<map>
 #include<vector>
#define ms(x,y) memset(x,y,sizeof x)
#define int long long 
const int maxn=2e5+10,INF = 0x3f3f3f3f ; 
using namespace std;
int a[maxn];
 void solve(){
     int n, m;
     cin >> n >> m;
     vector<int>l(n+1);  //左边界
     for (int i = 1; i <= m; i++) {
         int x, y;
         cin >> x >> y;
         if (x < y)swap(x, y);
         l[x] = max(l[x], y);
     }
     int sum = 0;
     int r = 1;
     for (int i = 1; i <=n; i++) {
         while (r + 1 <= n && l[r + 1] < i) ++r;
         sum += (r-i + 1);
     }
     cout << sum << '\n';
 }
signed main()
{
    ios::sync_with_stdio(false);
    int t;
    cin >> t;
    while (t--) {
        solve();
    }
}


G.Chevonne’s Necklace
思路:采用dp,01背包,可取大小视为体积,
因为选择移除的珍珠(p1,p2...)可取大小(ap1+ap2...)的和<=n,至少存在一个下一次选中的珍珠与上一次选中珍珠的距离dis>cpi,否则矛盾
故移除顺序不影响方案数,最终选中的珍珠是从珍珠1开始的连续编号.
 

#include<bits/stdc++.h>
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(fast) 
#include<iostream>
#include<algorithm>
#include<map>
#include<set>
#include<queue>
#include<cstring>
#include<math.h>
#include<map>
 #include<vector>
#define ms(x,y) memset(x,y,sizeof x)
#define int long long 
const int maxn=2e5+10,INF = 0x3f3f3f3f ; 
const int mod = 998244353;
using namespace std;
int a[maxn];
int dp[maxn];   //记录方案数,dp[i]表示当取i个珍珠时的最大方案数
bool vis[maxn];
void solve(){
     int n;
     cin >> n;
     for (int i = 0; i<n; i++) {
         cin >> a[i];
     }
     dp[0] = 1;
     vis[0] = 1;
     for (int i = 0; i < n; i++) {  //枚举珍珠编号
         if (a[i] >= 1) {
             for (int j = n; j >= a[i]; j--) {    //01
                 vis[j] |= vis[j-a[i]];   //记录珍珠状态
                 dp[j] = (dp[j] + dp[j - a[i]]) % mod;
             }
         }
     }
     int sum = n;
     while (!vis[sum]) {
         sum--;
     }
     cout << sum << ' ' << dp[sum]%mod << '\n';
 }
signed main()
{
    ios::sync_with_stdio(false);
        solve();
}


G - ORXOR
思路:状态压缩,枚举所有状态,对标记点集合异或,集合元素或运算
 

#include<bits/stdc++.h>
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(fast) 
#include<iostream>
#include<algorithm>
#include<map>
#include<set>
#include<queue>
#include<cstring>
#include<math.h>
#include<map>
 #include<vector>
 #include<stack>
#define ms(x,y) memset(x,y,sizeof x)
#define int long long 
const int maxn=2e5+10,INF = 1e18 ; 
using namespace std;
int a[maxn];
 void solve(){
     int n;
     cin >> n;
     for (int i = 0; i < n; i++) {
         cin >> a[i];
     }
     int Min = INF;
     for (int i = 0; i <(1<<n); i++) {   //枚举所有状态
         int t1=0, t2=0;
         for (int j = 0; j <= n; j++) {  //枚举所有元素,多一次进行最终合并
             if (j < n)  t1 |= a[j];      //|00为0
             if (j == n || i & ((1) << j)) {
                 t2 ^= t1;
                 t1 = 0;
             }
         }
         Min = min(Min, t2);
     }
     cout << Min << '\n';
 }
signed main()
{
    ios::sync_with_stdio(false);
    int t;
    solve();
}

C:Hamiltonian Wall
题意:能否一笔把B格子全部画完(一笔画完)
思路:使用dp,记录最后一个B位置和第一个B位置,若最后一列的B能否由开头转移过来,则YES,否则NO
转移的策略有三种,
1.一列有两个B,转移位置与上一列B转移位置相异;
2.一列有一个B,位置与上一列(一个B)位置相同
3.一列有一个B,位置与上一列(两个B)转移位置相同

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(fast) 
#include<iostream>
#include<algorithm>
#include<map>
#include<set>
#include<queue>
#include<cstring>
#include<math.h>
#include<map>
 #include<vector>
 #include<stack>
#define ms(x,y) memset(x,y,sizeof x)
#define int long long 
const int maxn=2e5+10,INF = 1e18 ; 
using namespace std;
int a[3][maxn];
int f[maxn][3];   
 void solve(){
     int n;
     cin >> n;
     for (int i = 1;i<=2; i++) {
         for (int j = 1; j <= n; j++) {
             char c;
             cin >> c;
             if (c == 'B')
                 a[i][j] = 1;
             else
                 a[i][j] = 0;
         }
     }
     int Min = n+1, Max = -1, flag = 0;
     for (int i = 1; i <= n; i++) {
         f[i][1] = 0;
         f[i][2] = 0;
         if (a[1][i] || a[2][i]) {
             Min = min(Min, i);
             Max = max(Max, i);
             flag = 1;
         }
     }
     if (!flag) {
         cout << "YES" << '\n';
         return;
     }
     f[Min][1] = (a[1][Min] == 1);
     f[Min][2] = (a[2][Min] == 1);
     for (int i = Min+1; i <= Max; i++) {
         if (a[1][i] == 1 && a[2][i] == 1) {
             f[i][1] = f[i - 1][2];
             f[i][2] = f[i - 1][1];
         }
         if (a[1][i] == 1 && a[2][i] == 0) {
             f[i][1] = f[i - 1][1];
         }
         if (a[1][i] == 0 && a[2][i] == 1) {
             f[i][2] = f[i - 1][2];
         }
     }
     if (f[Max][1] || f[Max][2]) {
         cout << "YES" << '\n';
     }
     else {
         cout << "NO" << '\n';
     }

 }
signed main()
{
    ios::sync_with_stdio(false);
    int t;
    cin >> t;
    while (t--) {
        solve();
    }
}


 

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值