记录下第一次一个人vp整场比赛,而且还打到金牌区啦~
虽然是省赛
比赛地址:Dashboard - The 2024 International Collegiate Programming Contest in Hubei Province, China - Codeforces
A
题意:给出 $x,y$ ,求 $a,b$ 满足:
$$
\sqrt{\frac{lcm(x,y)}{gcd(x,y)}}=a\sqrt{b}
$$
且 $a\times b$ 最大。
令 $a=1$ 即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 #include <bits/stdc++.h> using namespace std;#define LL long long int main () { int t; cin>>t; while (t--) { LL a,b; cin>>a>>b; LL ans=a*b/__gcd(a,b)/__gcd(a,b); cout<<1 <<" " <<ans<<endl; } return 0 ; }
B
题意:在二维平面上给出 $n$ 个点,在其中选取若干个点构成凸多边形且使多边形面积最小。$n\leq 100$
很明显构成三角形面积最小。直接暴力枚举三个顶点,求面积时用叉积即可。注意判断三角形是否存在。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 #include <bits/stdc++.h> using namespace std;pair<int ,int >v[200 ]; double cross (int i,int j,int k) { pair<int ,int >ij,ik; ij={v[i].first-v[j].first,v[i].second-v[j].second}; ik={v[i].first-v[k].first,v[i].second-v[k].second}; return (double )1 *abs (ij.first*ik.second-ij.second*ik.first)/2 ; } void solve () { int n; cin>>n; for (int i=1 ;i<=n;i++)cin>>v[i].first>>v[i].second; double ans=9999999999 ; for (int i=1 ;i<=n;i++) { for (int j=1 ;j<=n;j++) { for (int k=1 ;k<=n;k++) { if (i==j || j==k || i==k)continue ; double tmp=cross (i,j,k); if (tmp>0.1 ) ans=min (cross (i,j,k),ans); } } } if (ans==9999999999 || ans<0.5 )cout<<-1 <<endl; else cout<<ans<<endl; } int main () { int t; cin>>t; while (t--)solve (); return 0 ; }
E
水题
G
题意:在一个 $19\times 19$ 的棋盘上下围棋,给出每一步之后黑棋和白起分别被提多少颗。
一个大模拟题,时限4s,可以暴力过。
每一步都全局dfs一次,先找对方每一个块的气,若气为零就把这个块清除掉,然后再找下棋方每一个块的气。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 #include <bits/stdc++.h> using namespace std;int bd[20 ][20 ];int t;bool v[20 ][20 ];int dx[4 ]={0 ,0 ,1 ,-1 };int dy[4 ]={1 ,-1 ,0 ,0 };int sum;int ans;vector<pair<int ,int > >qz; void dfs (int x,int y) { qz.push_back ({x,y}); v[x][y]=1 ; for (int i=0 ;i<=3 ;i++) { int nx=x+dx[i]; int ny=y+dy[i]; if (nx<1 || nx>19 || ny<1 || ny>19 || v[nx][ny])continue ; if (bd[nx][ny]==0 )sum++; else if (bd[nx][ny]==t)dfs (nx,ny); } } void check () { memset (v,0 ,sizeof (v)); for (int i=1 ;i<=19 ;i++) { for (int j=1 ;j<=19 ;j++) { if (!v[i][j] && bd[i][j]==t) { qz.clear (); sum=0 ; dfs (i,j); if (!sum && qz.size ()) { ans+=qz.size (); for (auto i:qz) { bd[i.first][i.second]=0 ; } } } } } } int main () { ios_base::sync_with_stdio (false ); cin.tie (0 ); cout.tie (0 ); int n; cin>>n; for (int i=1 ,op=1 ;i<=n;i++,op^=3 ) { int x,y; cin>>x>>y; bd[x][y]=op; t=op^3 ; ans=0 ; check (); int ans1=ans; ans=0 ; t=op; check (); int ans2=ans; if (op==1 )cout<<ans2<<" " <<ans1<<endl; else cout<<ans1<<" " <<ans2<<endl; } return 0 ; }
H
题意:在一个 $1000\times 1000$ 的池塘里有不超过10个池塘有鱼,每个池塘的鱼不超过3条,现在用炸弹炸池塘,每次以炸弹为中心的“十”字范围内5个池塘每个池塘的鱼减少1条。求炸死所有的鱼最少需要多少次。
考虑状压dp来存状态。把状态构造成一个不超过10位的四进制数,存下所有能炸到鱼的位置,这样的位置不超过50个,然后用bfs的方法暴力炸鱼,最终状态为 $dp[0]$ 。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 #include <bits/stdc++.h> using namespace std;#define LL long long LL pow4[20 ]; int dp[2000005 ];int v[2000005 ];int n,m,k;bool check (LL st,int p) { st/=pow4[p]; st%=4 ; if (st)return 1 ; else return 0 ; } void de (long long status) { int dd[20 ]={0 }; int tot=0 ; while (status) { dd[++tot]=status%4 ; status/=4 ; } for (int i=k;i>=1 ;i--)cout<<dd[i];cout<<endl; } int main () { ios_base::sync_with_stdio (false ); cin.tie (0 ); cout.tie (0 ); pow4[0 ]=1 ; for (int i=1 ;i<=12 ;i++)pow4[i]=pow4[i-1 ]*4 ; cin>>n>>m>>k; LL status=0 ; map<pair<int ,int >,int >mp; vector<pair<int ,int > >pos; for (int i=1 ;i<=k;i++) { int x,y,cnt; cin>>x>>y>>cnt; mp[{x,y}]=i; pos.push_back ({x,y}); if (x>1 )pos.push_back ({x-1 ,y}); if (x<n)pos.push_back ({x+1 ,y}); if (y>1 )pos.push_back ({x,y-1 }); if (y<m)pos.push_back ({x,y+1 }); status+=pow4[i-1 ]*cnt; } int ans=0 ; queue<LL>q; bool flag=0 ; dp[status]=0 ; q.push (status); while (q.size ()) { LL sta=q.front (); q.pop (); int bit[20 ]={0 }; int tot=0 ; LL tst=sta; while (tst) { bit[tot++]=tst%4 ; tst/=4 ; } for (auto i:pos) { int x=i.first; int y=i.second; LL st=sta; if (mp[{x,y}]!=0 ) { if (bit[mp[{x,y}]-1 ])st-=pow4[mp[{x,y}]-1 ]; } if (mp[{x-1 ,y}]!=0 ) { if (bit[mp[{x-1 ,y}]-1 ])st-=pow4[mp[{x-1 ,y}]-1 ]; } if (mp[{x+1 ,y}]!=0 ) { if (bit[mp[{x+1 ,y}]-1 ])st-=pow4[mp[{x+1 ,y}]-1 ]; } if (mp[{x,y-1 }]!=0 ) { if (bit[mp[{x,y-1 }]-1 ])st-=pow4[mp[{x,y-1 }]-1 ]; } if (mp[{x,y+1 }]!=0 ) { if (bit[mp[{x,y+1 }]-1 ])st-=pow4[mp[{x,y+1 }]-1 ]; } if (!v[st]) { v[st]=1 ; dp[st]=dp[sta]+1 ; q.push (st); } } } cout<<dp[0 ]; return 0 ; }
J
题意:给出一个长为 $n$ 的数组 $a$ ,每次任选两个数将其删除并将这两个数的平均数加入数组。求最后的数的期望。
可以猜测最后的数就是平均数,因为每个数被选的概率相同。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 #include <bits/stdc++.h> using namespace std;const int mod=998244353 ;long long qsm (long long base, long long power) { long long result = 1 ; while (power > 0 ) { if (power & 1 ) result = result * base % mod; power >>= 1 ; base = (base * base) % mod; } return result; } int main () { int n; cin>>n; long long sum=0 ; for (int i=1 ;i<=n;i++) { int x; cin>>x; sum=(sum+x)%mod; } long long d=qsm (n,mod-2 ); sum=(sum*d)%mod; cout<<sum; return 0 ; }
L
题意:有一个包含无数多个整数点的完全图,任两个点的距离 $d(i,j)=lcm(i,j)$ 。先给出两个点 $a,b$ ,求这两个点的最短路。
分类讨论,假设 $a<b $:
若 $a=b $ ,答案是0;
若 $b%a=0$ ,答案是 $b$ ;
若 $gcd(a,b)!=1$ ,答案是 $a+b$ ;
若 $gcd(a,b)=1$ ,那么从 $a$ 到 $b$ 只可能经过 $a$ 、$b$ 、$2$ 、$a$ 的最小质因数、$b$ 的最小质因数。找出这5个数两两的距离跑floyed即可。若分类讨论很可能漏情况。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 #include <bits/stdc++.h> using namespace std;#define int long long const int inf=1e9 ;int Lcm (int a,int b) { return a*b/__gcd(a,b); } void solve () { int a,b; cin>>a>>b; if (a>b)swap (a,b); if (a==b) { cout<<0 <<endl; return ; } if (b%a==0 ) { cout<<b<<endl; return ; } if (__gcd(a,b)!=1 ) { cout<<a+b<<endl; return ; } int yza=0 ,yzb=0 ; for (int i=2 ;i<=sqrt (a);i++) { if (a%i==0 ) { yza=i; break ; } } if (!yza)yza=inf; for (int i=2 ;i<=sqrt (b);i++) { if (b%i==0 ) { yzb=i; break ; } } if (!yzb)yzb=inf; int f[10 ][10 ]; memset (f,0x3f ,sizeof (f)); for (int i=1 ;i<=5 ;i++)f[i][i]=0 ; int tmp[6 ]={0 ,a,b,2 ,yza,yzb}; for (int i=1 ;i<=5 ;i++) { for (int j=1 ;j<=5 ;j++) { if (i==j)f[i][j]=0 ; else f[i][j]=Lcm (tmp[i],tmp[j]); } } for (int k=1 ;k<=5 ;k++) { for (int i=1 ;i<=5 ;i++) { for (int j=1 ;j<=5 ;j++) { f[i][j]=min (f[i][j],f[i][k]+f[k][j]); } } } cout<<f[1 ][2 ]<<endl; } signed main () { int t; cin>>t; while (t--)solve (); return 0 ; }