SMU Winter 2024 Round #2 (Div.2)题解
A.P6056 [加油武汉] SIR 模型
思路
注意全感染和全恢复的情况
代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
int n, a[100005],t[100005]={0};
char c[100005];
int32_t main() {
int T;
//cin>>T;
T = 1;
while (T--) {
int s,i,r=0;
double b,y;
cin>>s>>i>>n>>b>>y;
for(int j=0;j<n;j++){
int x=ceil(b*s*i),m=ceil(y*i);
if(s>=x){
i+=(x-m);
s-=x;
}else{
i+=(s-m);
s=0;
}
r+=m;
}
cout<<s<<' '<<i<<' '<<r<<endl;
}
return 0;
}
B.P1765 手机
代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
int n, a[100005],t[26]={1,2,3,1,2,3,1,2,3,1,2,3,1,2,3,1,2,3,4,1,2,3,1,2,3,4};
char c[100005];
int32_t main() {
int T;
//cin>>T;
T = 1;
while (T--) {
cin.getline(c,1323);
int s=0;
for(int i=0;i<strlen(c);i++){
if(c[i]==' ')s++;
else if(c[i]>='a'&&c[i]<='z')s+=t[c[i]-'a'];
}
cout<<s;
}
return 0;
}
C.P4305 [JLOI2011] 不重复数字
思路
用哈希表去重
代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
unordered_map<int,int> hm;
int a[100005],n;
int32_t main() {
int T;
cin>>T;
//T = 1;
while (T--) {
cin>>n;
int pos=0;
for(int i=0;i<n;i++){
cin>>a[pos];
if(hm.find(a[pos])!=hm.end()){
hm[a[pos]]++;
}else{
hm[a[pos]]=1;
pos++;
}
}
for(int i=0;i<pos;i++){
cout<<a[i]<<' ';
}cout<<endl;
hm.clear();
}
return 0;
}
D.P1145 约瑟夫
思路
枚举m即可
代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
unordered_map<int,int> hm;
int a[100005],k,mn=INT64_MAX;
int32_t main() {
int T;
//cin>>T;
T = 1;
while (T--) {
cin>>k;
int m=k+1,f=0;
while(!f){
int pos=0;
for(int i=0;i<k;i++){
pos=(pos+m-1)%(2*k-i);
if(pos<k)break;
if(i==k-1)f=1;
}if(f)break;
m++;
}
cout<<m<<endl;
}
return 0;
}
E.P8742 [蓝桥杯 2021 省 AB] 砝码称重
思路
变种背包问题,计算方案数即可
代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
unordered_map<int, vector<int> > hm;
int a[100005], n,f[105][100005];
int32_t main() {
int T;
//cin>>T;
T = 1;
while (T--) {
cin >> n;
int s = 0, sum = 0;
for (int i = 1; i <= n; i++) {
cin >> a[i];
sum += a[i];
}
for(int i=1;i<=n;i++){
for(int j=sum;j;j--){
if(j==a[i])f[i][j]=1;
else if(f[i-1][j])f[i][j]=1;
else if(f[i-1][j+a[i]])f[i][j]=1;
else if(f[i-1][abs(j-a[i])])f[i][j]=1;
}
}
for(int i=1;i<=sum;i++){
if(f[n][i])s++;
}
cout<<s;
}
return 0;
}
F.P6473 [NOI Online #2 入门组] 未了
思路
贪心,先降序排序,存前缀和,再二分查找
代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
unordered_map<int, vector<int> > hm;
int a[200005], n,b[200005]={0};
int32_t main() {
int T;
//cin>>T;
T = 1;
while (T--) {
int l,v,sum=0;
cin >> n>>l>>v;
double t=(double)l/v;
for(int i=0;i<n;i++){
cin>>a[i];
sum+=a[i];
}
sort(a,a+n);
for(int i=1;i<=n;i++){
b[i]=b[i-1]+a[n-i];
}
int q;
cin>>q;
while(q--){
int x;
cin>>x;
if(x*v<l)cout<<0<<endl;
else if(x*v>=(l+sum))cout<<-1<<endl;
else{
cout<<upper_bound(b+1,b+n+1,x*v-l)-b<<endl;
}
}
}
return 0;
}
G.P8808 [蓝桥杯 2022 国 C] 斐波那契数组
思路
由\(a_0=a_1\)得,题目所定义的数组满足\(a_i=a_0*F_i\)(\(F_i\)为斐波那契数),则对所给数组的每个\(a_i\)分别判断是否能被\(F_i\)整除,并枚举修改次数
代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
unordered_map<int, vector<int> > hm;
int a[200005], n,b[200005]={1,1},mn=INT64_MAX;
int32_t main() {
int T;
//cin>>T;
T = 1;
while (T--) {
cin>>n;
for(int i=0;i<n;i++){
cin>>a[i];
}
int s=0;
if(a[0]!=a[1])s++;
int q=a[0]*2,p=a[0];
for(int i=2;i<n;i++){
if(a[i]!=q)s++;
b[i]=q/a[0];
q=p+q;
p=q-p;
}
mn=s;
int t;
for(int i=1;i<n;i++){
if(a[i]%b[i]==0){
t=a[i]/b[i];
s=0;
for(int i=0;i<n;i++){
if(a[i]!=t*b[i])s++;
}
mn=min(s,mn);
}
}
cout<<mn;
}
return 0;
}
H.[ABC325E] Our clients, please wait a moment
思路
\(dij\)算法,由题可知,可以从坐车切换为坐火车,但不能从坐火车切换为坐车,记车为0,火车为1,\(MN[i][0]\)为坐车到节点\(i\)的最少时间,\(MN[i][1]\)为坐火车到节点\(i\)的最少时间。
可以写出状态更新方程\(\begin{cases} MN[i][0]=min(MN[i][0],MN[m][0] + D[m][i] * A)\\ MN[i][1]=min(MN[i][1],min(MN[m][0],MN[m][1]) + D[m][i] * B + C)\\ \end{cases}\)
最后暴力枚举
代码
#include <bits/stdc++.h>
#define int long long
#define MAX (int)1e18
using namespace std;
unordered_map<int, vector<int> > hm;
int a[1005][1005], n;
int u, p, o;
vector<int> g[1005], vis(1005, 0);
vector<vector<int>> mn(1005, vector<int>(2, MAX));
int32_t main() {
int T;
//cin>>T;
T = 1;
while (T--) {
cin >> n >> u >> p >> o;
int m = 0, x =MAX, y = MAX;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
cin >> a[i][j];
}
}
vis[0] = 1;
mn[0][0]=0;
mn[0][1]=0;
for (int t = 0; t < n; t++) {
int pos;
for (int i = 0; i < n; i++) {
if (!vis[i]) {
mn[i][0] = min(mn[i][0], mn[m][0] + a[m][i] * u);
mn[i][1] = min(mn[i][1], a[m][i] * p + o + min(mn[m][1], mn[m][0]));
if (x >= mn[i][0] && y >= mn[i][1]) {
x = mn[i][0];
y = mn[i][1];
pos = i;
}
}
mn[i][0]=min(mn[i][0],mn[m][0]+a[m][i]*u);
mn[i][1]=min(mn[i][1],a[m][i] * p + o + min(mn[m][1], mn[m][0]));
}
m=pos;
vis[m]=1;
x = MAX, y =MAX;
}
cout << min(mn[n - 1][0], mn[n - 1][1]);
}
return 0;
}
I.P8786 [蓝桥杯 2022 省 B] 李白打酒加强版
思路
记\(a[i][j][k]\)为第\(i\)次看了\(j\)次花还剩\(k\)斗酒的方案数。
dp方程为\(\begin{cases} a[i+1][j+1][k-1]=(a[i][j][k]+a[i+1][j+1][k-1])(mod_{10000})\\ a[i+1][j][k*2]=(a[i][j][k]+a[i+1][j][k*2])(mod_{10000})\\ \end{cases}\)
注意\(k\)的范围即可。
代码
#include <bits/stdc++.h>
#define int long long
#define MOD 1000000007
using namespace std;
unordered_map<int, vector<int> > hm;
int a[205][105][105], n,m;
int32_t main() {
int T;
//cin>>T;
T = 1;
while (T--) {
cin>>n>>m;
a[0][0][2]=1;
for(int i=0;i<m+n;i++){
for(int j=0;j<m;j++){
for(int k=0;k<m;k++){
if(k)a[i+1][j+1][k-1]=(a[i][j][k]+a[i+1][j+1][k-1])%MOD;
if(2*k<=100)if(k)a[i+1][j][k*2]=(a[i][j][k]+a[i+1][j][k*2])%MOD;
}
}
}
cout<<a[m+n][m][0];
}
return 0;
}
J.P1685 游览
思路
拓扑排序,每次更新入度为0的点,dp方程为\(\begin{cases} cnt[v]+=cnt[u]\\ s[v]+=s[u]+cnt[u]*w\\ \end{cases}\)
代码
#include <bits/stdc++.h>
#define int long long
#define MAX (int)1e18
using namespace std;
unordered_map<int, vector<int> > hm;
int n,x,y,t,sum=0;
vector<pair<int,int>> g[10005];
vector<int> cnt(10005, 0),ru(10005, 0);
vector<int> mn(10005, 0);
vector<int > q;
void f(int s){
for(int i=0;i<g[s].size();i++){
cnt[g[s][i].first]=(cnt[g[s][i].first]+cnt[s])%10000;
mn[g[s][i].first]=(mn[g[s][i].first]+mn[s]+cnt[s]*g[s][i].second)%10000;
ru[g[s][i].first]--;
if(!ru[g[s][i].first])f(g[s][i].first);
}
}
int32_t main() {
int T;
//cin>>T;
T = 1;
while (T--) {
int m,s;
cin >> n >> m>>x>>y>>t;
for (int i = 0; i < m; i++) {
int u,v,w;
cin>>u>>v>>w;
u--;v--;
g[u].emplace_back(make_pair(v,w));
ru[v]++;
}
cnt[x-1]=1;
f(x-1);
cout<<(mn[y-1]+t*(cnt[y-1]-1))%10000;
}
return 0;
}