WZU_校赛补题

2025 WZU校赛补题

A.奖金发放

题面描述

温州大学第十八届“小橙教育杯”大学生程序设计竞赛的奖金是特等奖480元/队,一等奖240元/队,二等奖120元/队,三等奖60元/队,最佳女队奖120元/队。按评奖规定,特等奖1队(可能空缺),一等奖10队或8%有效参赛队数(以少者为准,下同),二等奖20队或16%有效参赛队数,三等奖30队或24%有效参赛队数,最佳女队奖1队(可能空缺)。如果有效队数已知,获奖队数按四舍五入计算。问奖金发放总额最多是多少,最少又是多少?

输入格式:

先输入整数t,表示问题个数。然后输入t个整数,表示有效参赛队数。

输出格式:

对每个问题,在一行内输出奖金发放总额的最大值和最小值,用一个空格隔开。所有数据都不会超过int型变量的范围。

输入样例:

3
107
58
148

输出样例:

6360 5760
3720 3120
7200 6600

AC code:

void solve(){
    int n;cin>>n;
    int num1=min((int)round((double)n*0.08),10);
    int num2=min((int)round((double)n*0.16),20);
    int num3=min((int)round((double)n*0.24),30);
    int ans=num1*240+num2*120+num3*60;
    cout<<ans+600<<' '<<ans<<endl;
}

B.Hole Enthusiast

题面描述

A hole enthusiast ACMer has a peculiar habit: whenever he
sees a number, he can't help but count the number of "holes" in it. The digit 0 has one hole, 1, 2, 3, 4, 5, and 7 have no holes, 6 and 9 have one hole, and 8 has two holes. Therefore, the total number of holes in a number is the sum of the holes in each of its digits. For example, the number 68530 has a
total of 4 holes.

Input:

The first line contains an integer T(1≤T≤10), representing the number of test cases. Each test case contains a non-negative
integer n(0≤n≤2×109 ), without leading zeros.

Output:

For each test case, output a single line containing the total number of holes in the number.

Sample Input:

3
68530
4517
108

Sample Output:

4
0
3

AC code:

map<char,int>mp={{'0',1},{'6',1},{'8',2},{'9',1}};
void solve(){
    string s;cin>>s;
    ll ans=0;
    for(int i=0;i<s.size();i++) ans+=mp[s[i]];
    cout<<ans<<endl;
}

C.江滨路对岸的风景(1)

题面描述

江滨路对岸绿水青山,风景优美。漫步也好、骑行也罢,抑或驱车,美不胜收的景色让人心旷神怡。可是城市规划与建设出了点问题,商家、机构、私人会所纷纷在江滨路的水岸一侧违章修建了各种建筑物,美其名曰“江景轩”“水岸生活”“岸芷汀兰”,挡住了江滨路上观光客眺望对岸的视线。

设想江滨路是直线上分布的一系列整数格点{1,2,⋯,n},违章建筑是一个整数线段[ai,bi](1≤ ai≤bi≤n,i=1,⋯,m),表示遮挡了江滨路上的一段连续的整数格点ai,ai+1,⋯,bi
。有q个观光客,每个观光客从江滨路的sj​ 格点步行(骑行或驱车)到t j​ 格点(1≤sj​≤tj​≤n,j=1,⋯,q),问每个观光客能看到多少对岸的风景,即路段[sj​,tj​]风景没被遮挡的格点数是多少。

输入格式:

先输入n,m和q,分别表示违章建筑数量和观光客人数。(1≤n,m,q≤1000)

然后输入2m个整数a1,b1,a2,b2,⋯,am,bm,表示各个建筑物线段。(1≤ai≤bi≤n)然后输入2q个整数s1,t1,s2,t2,⋯,sq,tq,表示各个观光客的观光路段。(1≤sj≤tj≤n)

输出格式:

对于每个询问,输出一行整数,表示能看见的风景长度(没被遮挡的格点数)。

输入样例:

12 5 3
1 5 4 6 9 9 1 2 8 10
1 12 2 9 5 5

输出样例:

3
1
0

AC code:

#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
typedef long long ll;
int main(){
    cin.tie(0)->ios::sync_with_stdio(false);
    int n,m,q;    
    cin>>n>>m>>q;    
    vector<int>a(n+1);
    for(int i=1,x,y;i<=m;i++) {
        cin>>x>>y;
        for(int j=x;j<=y;j++) a[j]=1;
    }
    for(int i=1,x,y;i<=q;i++){
        ll ans=0;
        cin>>x>>y;
        for(int j=x;j<=y;j++) if(!a[j]) ans++;
        cout<<ans<<endl;
    }
    return 0;
}

D.栅格填数

题面描述

栅格填数在计算机图形显示中有很多应用。填数方式有两种,设要填的范围是一个N行M列的矩阵。一种填法是填完上一行再填下一行,每个从左往右填,依次填入从1开始的连续整数,一直到N×M。另一种填法是填完左列再填右列,每列从上往下,依次填入从1开始的连续整数。
例如:当N=2,M=4,栅格的两种填数结果是

两种填法在同一位置数字相同的栅格已用黄色标出,共有2个。对任意的正整数N,M,数字相同的栅格有几个呢?

输入格式:

第一行输入问题整数T,表示问题的个数。接下来T行,每行输入两个整数N和M,表示矩阵的行数和列数。
(T≤1000, 1≤N,M≤2×109)

输出格式:

输出T行,为每个问题的答案,即两种填法数字相同的栅格数。

输入样例:

1
2 4

输出样例:

2

解题思路:

注意到,aij=n*(i-1)+j,而bij=i+(j-1)*m,要找到两矩阵重复元素出现个数,就要求aij=bij的个数,尝试化简式子
n*(i-1)+j=i+(j-1)*m
i*(n-1)-n=j*(m-1)-m
i*(n-1)-n-1=j*(m-1)-m-1
(i-1)*(n-1)=(j-1)*(m-1)
即求(i-1)/(j-1)=(m-1)/(n-1)满足这样条件的ij个数,求最大公约数就可以啦

AC code:

void solve(){
    int n,m;cin>>n>>m;
    cout<<__gcd(n-1,m-1)+1<<endl;
}

E.多多益善

题面描述

我也想编个好的故事给你们当题目,可是并没这能力。直接说我的意思吧。
有很多好东西,让你拣,你最多只能拣走总重量W的东西,每样东西的重量和价值都是已知的。对单件东西,你也可以掰一部分来,掰来a%,价值也是它的a%。问你拣的总价值最多达到多少。

输入格式:

输入好东西的个数n,以及总重量W。再输入2n个正整数,w1 ,v1​,w2,v2 ,⋯,wn,vn ,分别是每个东西的重量和价值。1≤n≤w≤105。0<vi,wi<=104

输出格式:

对每个问题,在一行内输出奖金发放总额的最大值和最小值,用一个空格隔开。所有数据都不会超过int型变量的范围。

输入样例:

3 10
10 14
2 5
4 1

输出样例:

16.200

AC code:

#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
typedef long long ll;
const int N=2e5+10;
struct node{
    int a,b;
    double c;
    friend bool operator<(node a,node b){
        return a.c>b.c;
    }
}a[N];
int main(){
    cin.tie(0)->ios::sync_with_stdio(false);
    int n,w;cin>>n>>w;
    for(int i=1;i<=n;i++) cin>>a[i].a>>a[i].b,a[i].c=(double)a[i].b/a[i].a;
    sort(a+1,a+1+n);
    double ans=0;
    for(int i=1;i<=n&&w>0;){
        ans+=a[i].c;
        a[i].a--;
        w--;
        if(!a[i].a) i++;
    }
    cout<<fixed<<setprecision(3)<<ans<<endl;
    return 0;
}

F.整数K分解

题面描述

给定两个正整数N,K,问能否把N表示成恰好K个3m形式(m是非负整数)的整数之和?

输入格式:

第一行输入问题个数T。接下来T行,每行输入两个整数N和K。(0<N,K≤109)

输出格式:

输出T行,对于每个问题,如果可以输出 Yes,否则输出No。

输入样例:

2
5 3
4 3

输出样例:

Yes
No

解题思路:

注意到,K最大取值是n,最小取值是K的三进制中1的个数,三进制满足每三位可以进一位,那么
有K的取值可以为n,n-2,n-4,n-6...x(x是k的三进制中1的个数),
因此只需判断n与k的奇偶性并判断k是否在最小与最大区间中

AC code:

#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
typedef long long ll;
ll q_pow(int x){
    ll s=1;
    while(x){
        if(x&1){
            s=(s<<1)+s;
        }
        x>>=1;
    }
    return s;
}//3次幂计算
void solve(){
    ll n,k;cin>>n>>k;
    int Min=0,Max=n;
    int i=0;
    auto pren(n);
    while(n){
        i=0;
        while(q_pow(i)<=n) i++;
        i--;
        n-=q_pow(i);
        Min++;
    }
    cout<<((k>=Min&&k<=Max&&(pren-k)%2==0)?"Yes":"No")<<endl;
}
int main(){
    cin.tie(0)->ios::sync_with_stdio(false);
    int T;cin>>T;
    while(T--) solve();
    return 0;
}

J.丁税第五版

题面描述

作为一国之大司徒,制定一套丁税(面向个人的税收)方案责无旁贷。大司徒在推出前四版方案之后,仍觉不甚完美。他发现数据的“连续度”既可操作又极具识别性,决定以此确定税基。户部提供的数据是一个大小为n的正整数序列a1, a2,⋯,an​ ,而每个臣民具有两个表示身份的数s,t(1≤s,t≤n),他的税基就是子段a s ,⋯,a t 的连续度,即子段元素上下限之间没有出现的整数个数除以该子段的元素跨度。例如子段是(8, 2, 5, 2, 3),最小元是2,最大元是8,2~8跨度为7,其中没有出现的数字是4,6,7,共3个,所以税基为3/7。特别地,如果s=t,税基是0,表示特权臣民。
但是问题又来了,大批臣民只知道自己的s,t,于是纷纷来询问自己的税基。大司徒面对一大批臣民的询问,需要逐一回答。

输入格式:

先输入n,m,分别表示序列a的长度和询问次数。然后输入n个整数,表示序列元素ai 。最后输入2m个整数si,ti (1≤si≤t i≤n),表示臣民的身份数字。(1≤n,m≤50000,1≤ai≤50000)

输出格式:

对每次询问,输出臣民关心的税基,用最简分数格式(如3/7),独占一行。

输入样例:

10 4
5 3 5 5 4 2 2
4 8 2
1 8
7 10
2 5
1 3

输出样例:

0/1
4/7
0/1
1/3

解题思路:

本题是离线询问区间最值和在区间中元素种类的变式,离线询问区间最值直接st表就行了,喜欢莫队和树状数组的小朋友一眼就能看出来做法。
ps:如果强制在线可能会很麻烦,偶没学过。

AC code1(莫队):

#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
typedef long long ll;
const int N=2e5+10;
int a[20][N],b[20][N];
ll ans;
int cnt[N];
struct Q{
    int l,r,id,pos;
    friend bool operator<(Q a,Q b){
        return (a.pos==b.pos)?((a.pos&1)?(a.r<b.r):(a.r>b.r)):(a.l<b.l);
    }
}q[N];
int querymin(const int &l,const int &r){
    int len=__lg(r-l+1);
    return min(b[len][l],b[len][r-(1<<len)+1]);
}
int querymax(const int &l,const int &r){
    int len=__lg(r-l+1);
    return max(a[len][l],a[len][r-(1<<len)+1]);
}
void add(int x){
    int y=a[0][x];
    if(cnt[y]==0) ans++;
    cnt[y]++;
}
void sub(int x){
    int y=a[0][x];
    cnt[y]--;
    if(cnt[y]==0) ans--;
}
int main(){
    cin.tie(0)->ios::sync_with_stdio(false);
    int n,m;cin>>n>>m;
    int siz=sqrt(n+0.5);
    for(int i=1;i<=n;i++) cin>>a[0][i],b[0][i]=a[0][i];
    int len=__lg(n);
    for(int i=1;i<=len;i++){
        for(int j=1;j<=n-(1<<i)+1;j++){
            a[i][j]=max(a[i-1][j],a[i-1][j+(1<<i-1)]);
            b[i][j]=min(b[i-1][j],b[i-1][j+(1<<i-1)]);
        }
    }
    vector<pair<int,int>>res(m+1);
    for(int i=1,l,r;i<=m;i++){
        cin>>q[i].l>>q[i].r;
        q[i].id=i;
        q[i].pos=(q[i].l-1)/siz;
        res[i].second=querymax(q[i].l,q[i].r)-querymin(q[i].l,q[i].r)+1;
    }
    sort(q+1,q+1+m);
    int l=1,r=0;//经典左闭右闭写法
    for(int i=1;i<=m;i++){
        while(l>q[i].l) add(--l);
        while(r<q[i].r) add(++r);
        while(l<q[i].l) sub(l++);
        while(r>q[i].r) sub(r--);
        res[q[i].id].first=res[q[i].id].second-ans;
    }
    for(int i=1;i<=m;i++){
        if(res[i].first==0||res[i].second==0) res[i]={0,1};
        else {
            int base=__gcd(res[i].first,res[i].second);
            res[i].first/=base,res[i].second/=base;
        }
        cout<<res[i].first<<'/'<<res[i].second<<endl;
    }
    return 0;
}
//离线莫队维护区间可重性

AC code2(树状数组):

#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
typedef long long ll;
const int N=2e5+10;
struct Q{
    int l,idx;
};
int n,m;
int a[20][N],b[20][N],tree[N*2];
inline int lowbits(const int &x){ return x&-x; }
void add(int x,const int &k){
    while(x<=n){
        tree[x]+=k;
        x+=lowbits(x);
    }
}
int sum(int x){
    int ans=0;
    while(x){
        ans+=tree[x];
        x&=x-1;
    }
    return ans;
}
void init(){
    int len=__lg(n);
    for(int i=1;i<=len;i++){
        for(int j=1;j<=n-(1<<i)+1;j++){
            a[i][j]=max(a[i-1][j],a[i-1][j+(1<<i-1)]);
            b[i][j]=min(b[i-1][j],b[i-1][j+(1<<i-1)]);
        }
    }
}
int q_min(const int &l,const int &r){
    int len=__lg(r-l+1);
    return min(b[len][l],b[len][r-(1<<len)+1]);
}
int q_max(const int &l,const int &r){
    int len=__lg(r-l+1);
    return max(a[len][l],a[len][r-(1<<len)+1]);
}
int main(){
    cin.tie(0)->ios::sync_with_stdio(false);
    cin>>n>>m;
    for(int i=1;i<=n;i++) cin>>a[0][i],b[0][i]=a[0][i];
    init();
    vector<vector<Q>>query(n+1);
    for(int i=0,l,r;i<m;i++){
        cin>>l>>r;
        query[r].push_back(Q{l,i});
    }
    map<int,int>las;//每个元素最后出现的位置
    vector<pair<int,int>>res(m);
    for(int r=1;r<=n;r++){
        if(las.count(a[0][r])){
            add(las[a[0][r]],-1);
        }
        add(r,1);
        las[a[0][r]]=r;
        for(auto &q:query[r]){
            auto [l,idx]=q;
            int fenmu=q_max(l,r)-q_min(l,r)+1;
            int fenzi=fenmu-(sum(r)-sum(l-1));

            int base=__gcd(fenzi,fenmu);
            if(base==0) base=1,fenmu=1;
            fenzi/=base,fenmu/=base;
            res[idx]={fenzi,fenmu};
        }
    }
    for(auto &[x,y]:res){
        cout<<x<<'/'<<y<<endl;
    }
    return 0;
}
posted @ 2025-04-05 18:39  usedchang  阅读(46)  评论(0)    收藏  举报