CCSU2023暑期结训测试赛

A 666

将每个数组中的质因子分解,放到一个存质因子和每个质因子位置的二维数组中,每次查询在这个二维数组的质因子中查询最后和最前面的位置,相减即为答案

#include<bits/stdc++.h>
using namespace std;

#define endl '\n'
#define ll long long
#define fi first
#define se second

ll gcd(ll a,ll b) {
	return b ? gcd(b,a % b) : a;
}

ll power(ll a,ll b) {
	ll ans = 1;
	while(b) {
		if(b % 2 != 0)	ans *= a;
		a = a * a;
		b >>= 1;
	}
	return ans;
}

typedef pair<ll,ll> PII;
queue<PII> q;

const int N = 2e5 + 5;

ll g[2010][2010],d[2010][2010];
int dx[4] = {-1,0,1,0},dy[4] = {0,1,0,-1};

void solve() {
	int n;
    cin >> n;
    vector<vector<int>> a(n + 1);
    
    for(int i = 1; i <= n; i++) {
        int x;
        cin >> x;
        for(int j = 2; j * j <= x; j++) {
            if(x % j == 0) {
                while(x % j == 0) {
                    x /= j;
                }
                a[j].push_back(i);
            }
        }
        if(x > 1)    a[x].push_back(i);
    }
    
    int m;
    cin >> m;
    while(m--) {
        int l,r,x;
        cin >> l >> r >> x;
        int ans = upper_bound(a[x].begin(),a[x].end(),r) - lower_bound(a[x].begin(),a[x].end(),l);
        if(!ans)    cout << "666666!" << endl;
        else cout << ans << endl;
    }
}

int main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	
    int t;
//     cin >> t;
	t = 1;
    while(t--) {
    	solve();
    }
    	
    return 0;
}

B 求和

                                                                                 n                       n  
B:欧拉反演 n =  ∑   φ(n) ,对n属于N都成立.  那么 ∑   ⌊n|d⌋ φ(d) = ∑    ∑  φ(d)即对n求和
                        (d|n)                                                d=1                    i=1 d|i

#include<bits/stdc++.h>
using namespace std;

#define endl '\n'
#define ll long long
#define fi first
#define se second

ll gcd(ll a,ll b) {
	return b ? gcd(b,a % b) : a;
}

ll power(ll a,ll b) {
	ll ans = 1;
	while(b) {
		if(b % 2 != 0)	ans *= a;
		a = a * a;
		b >>= 1;
	}
	return ans;
}

typedef pair<ll,ll> PII;
queue<PII> q;

const int N = 2e5 + 5;
ll a[N];

ll g[2010][2010],d[2010][2010];
int dx[4] = {-1,0,1,0},dy[4] = {0,1,0,-1};

int fact(int n) {
	int s = 0,j = 0;
	
	while(n) {
		s = s + j * (n % 2);
		n /= 2;
		j *= 10;
	}
	
	return s;
}

/*ll f(ll x)
{
    ll res = x;
    for (int i = 2; i <= x / i; i ++ )
        if (x % i == 0) {
            res = res / i * (i - 1);
            while (x % i == 0) x /= i;
        }
    if (x > 1) res = res / x * (x - 1);

    return res;
}*/

void solve() {
    ll n;
    cin >> n;
    ll sum = 0;
    for(int i = 1; i <= n; i++) {
        sum += i;
    }
    
    cout << sum << endl;
}

int main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	
    int t;
    cin >> t;
// 	t = 1;
    while(t--) {
    	solve();
    }
    	
    return 0;
}

C 迷宫

将每个位置的数的位置坐标赋值到结构体中,循环每个位置的上下左右是否有比它权值小的数,若无则走不到终点

#include<bits/stdc++.h>
using namespace std;

#define endl '\n'
#define ll long long
#define fi first
#define se second

ll gcd(ll a,ll b) {
	return b ? gcd(b,a % b) : a;
}

ll power(ll a,ll b) {
	ll ans = 1;
	while(b) {
		if(b % 2 != 0)	ans *= a;
		a = a * a;
		b >>= 1;
	}
	return ans;
}

typedef pair<ll,ll> PII;
queue<PII> q;

const int N = 2e5 + 5;
// ll a[N];

ll g[2010][2010],d[2010][2010];
int dx[4] = {-1,0,1,0},dy[4] = {0,1,0,-1};

void solve() {
	int n,m;
    cin >> n >> m;
    
    vector<vector<int>> a(n + 1,vector<int> (m + 1));
    vector<PII> q(n * m + 1);
    
    for(int i = 1; i <= n; i++) {
        for(int j = 1; j <= m; j++) {
            cin >> a[i][j];
            q[a[i][j]] = {i,j};
        }
    }
    
    string ans = "YES";
    
    for(int i = 2; i <= n * m; i++) {
        bool f = 0;
        for(int j = 0; j < 4; j++) {
            int x = q[i].fi + dx[j];
            int y = q[i].se + dy[j];
            if(x < 1 || x > n || y < 1 || y > m)    continue;
            if(a[x][y] < i)    f = 1;
        }
        if(!f)    ans = "NO";
    }
    cout << ans << endl;
}

int main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	
    int t;
    cin >> t;
	
    while(t--) {
    	solve();
    }
    	
    return 0;
}

D 操作序列1

先将每个算法的位置对应赋值,若已经学会就将其和下一个算法进行合并,直至都合并到一个未学习过的算法中

#include<bits/stdc++.h>
using namespace std;

#define endl '\n'
#define ll long long
#define fi first
#define se second

ll gcd(ll a,ll b) {
	return b ? gcd(b,a % b) : a;
}

ll power(ll a,ll b) {
	ll ans = 1;
	while(b) {
		if(b % 2 != 0)	ans *= a;
		a = a * a;
		b >>= 1;
	}
	return ans;
}

typedef pair<ll,ll> PII;
queue<PII> q;

const int N = 2e6 + 5;
ll a[N];

ll g[2010][2010],d[2010][2010];
int dx[4] = {-1,0,1,0},dy[4] = {0,1,0,-1};

int find(int x) {
    return a[x] == x ? x : a[x] = find(a[x]);
}

void solve() {
	int n,m;
    cin >> n >> m;
    
    for(int i = 0; i <= n + 1; i++) {
        a[i] = i;
    }
    
    while(m--) {
        ll ans = 0;
        int l,r;
        cin >> l >> r;
        for(int i = find(l); i <= r; i = find(i + 1)) {
            ans++;
            a[i] = i + 1;
        }
        cout << ans << endl;
    }
}

int main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	
    int t;
//     cin >> t;
	t = 1;
    while(t--) {
    	solve();
    }
    	
    return 0;
}

F NB数

对操作次数进行二分,如果遇到不是NB数,操作次数减一将它变成0使它变成NB数,返回成立的操作次数,循环寻找最少的操作次数

#include<bits/stdc++.h>
using namespace std;

#define endl '\n'
#define ll long long
#define fi first
#define se second

ll gcd(ll a,ll b) {
	return b ? gcd(b,a % b) : a;
}

ll power(ll a,ll b) {
	ll ans = 1;
	while(b) {
		if(b % 2 != 0)	ans *= a;
		a = a * a;
		b >>= 1;
	}
	return ans;
}

typedef pair<ll,ll> PII;
queue<PII> q;

const int N = 1e5 + 5;
ll a[N],n,m;

ll g[2010][2010],d[2010][2010];
int dx[4] = {-1,0,1,0},dy[4] = {0,1,0,-1};

bool check(int x) {
    int ans = 0;
    for(int i = 1; i <= n; i++) {
        if(ans >= a[i]) {
            ans++;
        } else if(x) {
            x--;
            ans++;
        }
    }
    return ans >= m;
}

void solve() {
	cin >> n >> m;
    for(int i = 1; i <= n; i++)    cin >> a[i];
    int l = 0,r = m;
    while(l < r) {
        int mid = (l + r) >> 1;
        if(check(mid))    r = mid;
        else l = mid + 1;
    }
    cout << r << endl;
}

int main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	
    int t;
//     cin >> t;
	t = 1;
    while(t--) {
    	solve();
    }
    	
    return 0;
}

G 跑步计划

求最多能删除的边,如果i,j两点之间存在一点k使得i可以通过k到达j的距离比i直接到j的距离更短,那么此时i到j的这条边可以删除,无向图最后要删除的边需要除2

#include<bits/stdc++.h>
using namespace std;

#define endl '\n'
#define ll long long
#define fi first
#define se second

ll gcd(ll a,ll b) {
	return b ? gcd(b,a % b) : a;
}

ll power(ll a,ll b) {
	ll ans = 1;
	while(b) {
		if(b % 2 != 0)	ans *= a;
		a = a * a;
		b >>= 1;
	}
	return ans;
}

typedef pair<ll,ll> PII;
queue<PII> q;

const int N = 305;
ll a[N],cnt[N][N];

ll g[2010][2010],d[2010][2010];
int dx[4] = {-1,0,1,0},dy[4] = {0,1,0,-1};

int MIN(int a,int b) {
    return a < b ? a : b;
}

void solve() {
    memset(d,0x3f,sizeof d);
    int n,m;
    cin >> n >> m;
    for(int i = 1; i <= n; i++)    d[i][i] = 0;
    for(int i = 1; i <= m; i++) {
        int u,v,w;
        cin >> u >> v >> w;
        d[u][v] = MIN(d[u][v],w);
        d[v][u] = MIN(d[v][u],w);
        cnt[u][v] = 1;
        cnt[v][u] = 1;
    }
    for(int k = 1;  k <= n; k++) {
        for(int i = 1; i <= n; i++) {
            for(int j = 1; j <= n; j++) {
                d[i][j] = min(d[i][j],d[i][k] + d[k][j]);
            }
        }
    }
    ll ans = 0;
    for(int i = 1; i <= n; i++) {
        for(int j = 1; j <= n; j++) {
            if(i == j)    continue;
            for(int k = 1; k <= n; k++) {
                if(k == i || k == j)    continue;
                if(cnt[i][j] && d[i][j] == d[i][k] + d[k][j]) {
                    ans++;
                    break;
                }
            }
        }
    }
    cout << ans / 2;
}

int main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	
    int t;
//     cin >> t;
	t = 1;
    while(t--) {
    	solve();
    }
    	
    return 0;
}

H 中位数?中位序列!

通过枚举可以发现当k为偶数的情况下,中位序列都是k/2为开头,后面都是k的序列。k为奇数时,第一位一定是(k + 1) / 2(模拟就可得),后面需要进行1到n / 2次循环处理将(k + 1) / 2每次进行减一,当其本就是一时则将其删除(可以通过最简单的n为5 k为1样例模拟),而通过n为8,k为3的例子可得若最后一项删除并继续进行减一操作时,需要将其减一后在后一项添加一项赋值为k(不太懂啥原理只能模拟出来qwq)

#include<bits/stdc++.h>
using namespace std;

#define endl '\n'
#define ll long long
#define fi first
#define se second

ll gcd(ll a,ll b) {
	return b ? gcd(b,a % b) : a;
}

ll power(ll a,ll b) {
	ll ans = 1;
	while(b) {
		if(b % 2 != 0)	ans *= a;
		a = a * a;
		b >>= 1;
	}
	return ans;
}

typedef pair<ll,ll> PII;
queue<PII> q;

const int N = 2e5 + 5;
ll a[N];

ll g[2010][2010],d[2010][2010];
int dx[4] = {-1,0,1,0},dy[4] = {0,1,0,-1};

void solve() {
	int n,k;
    cin >> n >> k;
    
    if(k % 2 == 0) {
        cout << k / 2 << ' ';
        for(int i = 2; i <= n; i++) {
            cout << k << ' ';
        }
    } else {
        for(int i = 1; i <= n; i++)    a[i] = (k + 1) / 2;
        int tt = n;
        for(int i = 1; i <= n / 2; i++) {
            if(a[tt] == 1) {
                tt--;
            } else {
                a[tt]--;
                while(tt < n)    a[++tt] = k;
            }
        }
        for(int i = 1; i <= tt; i++) {
            cout << a[i] << ' ';
        }
    }
}

int main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	
    int t;
//     cin >> t;
	t = 1;
    while(t--) {
    	solve();
    }
    	
    return 0;
}

I 仙跳墙

将xyz存入一个判断数组cnt中,xyz的位置cnt为1,在cnt为0时进行dp,因为编号小的都在编号大的之前,所以确定最大的i和j更新答案,此时的答案就是在没有连续使用编号为xyz下的答案

#include<bits/stdc++.h>
using namespace std;

#define endl '\n'
#define ll long long
#define fi first
#define se second

ll gcd(ll a,ll b) {
	return b ? gcd(b,a % b) : a;
}

ll power(ll a,ll b) {
	ll ans = 1;
	while(b) {
		if(b % 2 != 0)	ans *= a;
		a = a * a;
		b >>= 1;
	}
	return ans;
}

typedef pair<ll,ll> PII;
queue<PII> q;

const int N = 105;
ll val[N],time1[N],cnt[N][N][N],dp[N][N][N];

ll g[2010][2010],d[2010][2010];
int dx[4] = {-1,0,1,0},dy[4] = {0,1,0,-1};

int max(int a,int b) {
    return a > b ? a : b;
}

void solve() {
	int n,T,m;
    cin >> n >> T >> m;
    for(int i = 2; i <= n + 1; i++) {
        cin >> val[i] >> time1[i];
    }
    for(int i = 1; i <= m; i++) {
        int x,y,z;
        cin >> x >> y >> z;
        x++;y++;z++;
        cnt[x][y][z] = 1;
    }
    
    ll ans = 0;
    
    for(int i = 2; i <= n + 1; i++) {
        for(int j = 0; j < i; j++) {
            for(int k = 0; k < j; k++) {
                if(!cnt[k][j][i]) {
                    for(int p = time1[i]; p <= T; p++) {
                        dp[i][j][p] = max(dp[i][j][p],dp[j][k][p - time1[i]] + val[i]);
                        ans = max(ans,dp[i][j][p]);
                    }
                }
            }
        }
    }
    
    cout << ans;
}

int main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	
    int t;
//     cin >> t;
	t = 1;
    while(t--) {
    	solve();
    }
    	
    return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值