第十三届山东省大学生程序设计竞赛
第十三届山东省大学生程序设计竞赛
A. Orders
解题思路:
对订单进行升序排序。
遍历每一天,我们每天生成
代码:
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
typedef pair<ll,ll> pii;
#define fi first
#define se second
int n,m,k;
void solve()
{
scanf("%d %d",&n,&k);
vector<pii> v(n + 1);
for(int i = 1;i<=n;i++)
{
scanf("%lld %lld",&v[i].fi,&v[i].se);
}
sort(v.begin()+1,v.end());
ll sum = 0;
ll last = 0;
for(int i = 1;i<=n;i++)
{
sum += (v[i].fi - last) * k;
last = v[i].fi;
if(sum >= v[i].se)
{
sum -= v[i].se;
}
else
{
printf("No\n");
return;
}
}
printf("Yes\n");
}
int main()
{
int t = 1;
scanf("%d",&t);
while(t--)
{
solve();
}
return 0;
}
I. Three Dice
解题思路:
直接暴力分类讨论即可。
代码1:
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
typedef pair<ll,ll> pii;
#define fi first
#define se second
int n,m,k;
void solve()
{
ll a,b;
scanf("%lld %lld",&a,&b);
vector<int> black;
black.push_back(2);
black.push_back(3);
black.push_back(5);
black.push_back(6);
map<int,bool> q;
n = black.size();
for(int i = 0;i<n;i++)
{
for(int j = 0;j<n;j++)
{
for(int k = 0;k<n;k++)
{
int res = black[i] + black[j] + black[k];
q[res] = true;
}
}
}
map<int,int> s;
for(int i = 0;i<n;i++)
{
for(int j = 0;j<n;j++)
{
int res = black[i] + black[j];
s[res] = 1;
}
}
if(a == 0)
{
for(auto c : q)
{
if(c.fi == b)
{
puts("Yes");
return;
}
}
puts("No");
return;
}
else if(a == 1)
{
for(auto c : s)
{
if(c.fi == b)
{
puts("Yes");
return;
}
}
puts("No");
return;
}
else if(a == 4)
{
for(auto c : s)
{
if(c.fi == b)
{
puts("Yes");
return;
}
}
puts("No");
return;
}
else if(a == 2)
{
if(b == 2 || b == 3 || b == 5 || b == 6)
{
puts("Yes");
return;
}
else
{
puts("No");
return;
}
}
else if(a == 5)
{
if(b == 2 || b == 3 || b == 5 || b == 6)
{
puts("Yes");
return;
}
else
{
puts("No");
return;
}
}
else if(a == 8)
{
if(b == 2 || b == 3 || b == 5 || b == 6)
{
puts("Yes");
return;
}
else
{
puts("No");
return;
}
}
else if(a == 3)
{
if(b != 0)
{
puts("No");
return;
}
else
{
puts("Yes");
return;
}
}
else if(a == 12)
{
if(b != 0)
{
puts("No");
return;
}
else
{
puts("Yes");
return;
}
}
puts("No");
}
int main()
{
int t = 1;
// scanf("%d",&t);
while(t--)
{
solve();
}
return 0;
}
优雅的题解思路代码(推荐):
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
typedef pair<ll,ll> pii;
#define fi first
#define se second
int n,m,k;
int a[] = {0,1,0,0,4,0,0};
int b[] = {0,0,2,3,0,5,6};
void solve()
{
scanf("%d %d",&n,&m);
for(int i = 1;i<=6;i++)
{
for(int j = 1;j<=6;j++)
{
for(int k = 1;k<=6;k++)
{
if(a[i] + a[j] + a[k] == n && b[i] + b[j] + b[k] == m)
{
puts("Yes");
return;
}
}
}
}
puts("No");
}
int main()
{
int t = 1;
// scanf("%d",&t);
while(t--)
{
solve();
}
return 0;
}
G. Matching
解题思路:
公式变换:
不难发现,
所以,我们每次选取一个集合中
代码:
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
typedef pair<ll,ll> pii;
#define fi first
#define se second
int n,m,k;
void solve()
{
scanf("%d",&n);
vector<ll> a(n + 1);
map<ll,vector<ll>> q;
for(int i = 1;i<=n;i++)
{
scanf("%lld",&a[i]);
ll res = a[i] - i;
q[res].push_back(a[i]);
}
ll ans = 0;
for(auto &t : q)
{
vector<ll> &v = t.se;
sort(v.begin(),v.end());
for(int i = v.size()-1;i > 0;i--)
{
ll a = v[i];
ll b = v[i-1];
if(a + b > 0)
{
ans += a + b;
i --;
}
}
}
printf("%lld\n",ans);
}
int main()
{
int t = 1;
scanf("%d",&t);
while(t--)
{
solve();
}
return 0;
}
D. Fast and Fat
解题思路:
-
二分队伍速度
. -
对于速度大于等于
的队员,他们的极限承重能力为 ,我们可进行公式推导:所以,我们可以记录可背人队员的承重极限,然后和速度小于
的队员进比较,分配任务。贪心地想,从最轻的落后队员开始看,尽量让承重极限小的队员背他,以此类推。
代码:
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
typedef pair<ll,ll> pii;
#define fi first
#define se second
int n,m,k;
void solve()
{
scanf("%d",&n);
vector<ll> v(n + 1),w(n + 1);
vector<pair<ll,int>> a(n + 1);
vector<pair<pair<ll,ll>,int>> q(n + 1);
for(int i = 1;i<=n;i++)
{
scanf("%lld %lld",&v[i],&w[i]);
a[i] = {v[i] + w[i],i};
q[i] = {{w[i],v[i]},i};
}
sort(q.begin() + 1,q.end());
sort(a.begin() + 1,a.end());
int l = 0;
int r = 1e9 + 1;
auto check = [&](int x)
{
vector<int> t,ans;
vector<bool> st(n + 1);
for(int i = 1;i<=n;i++)
{
if(q[i].fi.se < x)
{
st[q[i].se] = true;
t.push_back(q[i].fi.fi);
}
}
for(int i = n;i>=1;i--)
{
if(!st[a[i].se])
{
ans.push_back(a[i].fi - x);
}
}
reverse(ans.begin(),ans.end());
if(ans.size() < t.size())
{
return false;
}
int idx = ans.size()-1;
for(int i = t.size()-1;i>=0 && idx >= 0;i--)
{
while(idx >= 0 && ans[idx] < t[i])
{
idx --;
}
if(idx >= 0)
{
idx --;
t[i] = 0;
}
else
{
break;
}
}
if(t.empty() || t[0] == 0)
{
return true;
}
return false;
};
while(l + 1 < r)
{
int mid = l + r >> 1;
// cout<<mid<<endl;
if(check(mid))
{
l = mid;
}
else
{
r = mid;
}
}
printf("%d\n",l);
}
int main()
{
int t = 1;
scanf("%d",&t);
while(t--)
{
solve();
}
return 0;
}
L. Puzzle: Sashigane
解题思路:
不难发现,我们围着块周围铺全覆盖的
一共n层,开头有了一层,我们还需要铺
自己画图试一下就好。
代码:
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
using i128 = __int128;
typedef pair<ll,ll> pii;
#define fi first
#define se second
void solve()
{
int n,a,b;
scanf("%d %d %d",&n,&a,&b);
int u = a;
int d = a;
int l = b;
int r = b;
printf("Yes\n%d\n",n-1);
for(int i = 1;i <= n - 1;i++)
{
// cout<<i<<endl;
//Èç¹ûÑ¡(u-1,l-1)
if(u > 1 && l > 1)
{
u --;
l --;
printf("%d %d %d %d\n",u,l,d - u, r - l);
}
else if(u > 1 && r < n)
{
u --;
r ++;
printf("%d %d %d %d\n",u,r,d - u,l - r);
}
else if(d < n && l > 1)
{
// cout<<1<<endl;
d ++;
l --;
printf("%d %d %d %d\n",d,l,u - d,r - l);
}
else if(d < n && r < n)
{
d ++;
r ++;
printf("%d %d %d %d\n",d,r,u - d,l - r);
}
// printf("udlr : %d %d %d %d\n",u,d,l,r);
}
}
int main()
{
int t = 1;
// scanf("%d",&t);
while(t--)
{
solve();
}
return 0;
}
E. Math Problem
解题思路:
首先,我们能够发现如果我们执行一次
不难发现,如果我们一直进行
如果我们在执行完了
那么执行
公式推导:
暴力带入
假设进行完除法得到的当前数为
即使
也就是说
由上可知:乘法的最大执行次数大概也是
所以,总时间复杂度为
代码:
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
using i128 = __int128;
typedef pair<ll,ll> pii;
#define fi first
#define se second
ll qmi(ll a,ll b)
{
ll res = 0;
while(b)
{
if(b & 1)
{
res = (res * a);
}
}
}
void solve()
{
ll n,k,m,a,b;
scanf("%lld %lld %lld %lld %lld",&n,&k,&m,&a,&b);
if(n % m == 0)
{
printf("0\n");
return ;
}
if(k == 1)
{
printf("-1\n");
return;
}
ll ans = 1e18;
i128 cur = n;
for(int i = 0;;i++,n /= k)
{
if(n == 0)
{
ans = min(ans,i * b);
break;
}
i128 l = n;
i128 r = n;
ll res = i * b;
while(r / m == l / m && l % m)
{
l *= k;
r = r * k + k - 1;
res += a;
}
ans = min(ans,res);
}
cout<<ans<<endl;
}
int main()
{
int t = 1;
scanf("%d",&t);
while(t--)
{
solve();
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】