2026牛客寒假算法基础集训营6(K H G B A)
K 小L的游戏1 思路: 问最后一次操作是谁进行的,先计算一下最多能进行多少次两人操作,然后再看是增加 m 超过 z 还是增加 m+n 超过 z。代码:
1 2 3 4 5 6 7 8 9 void solve () { int m,n,z; cin>>m>>n>>z; int cnt=(z-1 )/(m+n); int ans=cnt*(m+n); if (ans+m>=z)cout<<"0" ; else cout<<"1" ; }
H 小L的数组 思路: 一共就两种操作,按位异或是不会超过 2048 的所以开个 2048 的数组就可以。用 dp[i] 来表示这个数字能否到达,然后进行 n 步操作,每一步操作都有一个内循环去处理之前操作所能到达的值。注意不要在内循环中直接去修改 dp 数组这样会导致错误,所以先用一个 ne 数组去存储。 然后从大到小找所能到达的最大值即可。代码:
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 #include <bits/stdc++.h> using namespace std;#define int long long #define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0); #define endl '\n' const int N=2100 ;int a[N],b[N];bool dp[2048 ],ne[2048 ];void solve () { int n; cin>>n; for (int i=1 ;i<=n;i++) { cin>>a[i]; } for (int i=1 ;i<=n;i++) { cin>>b[i]; } memset (dp,0 ,sizeof dp); dp[0 ]=1 ; for (int i=1 ;i<=n;i++) { memset (ne,0 ,sizeof ne); for (int x=0 ;x<2048 ;x++) { if (!dp[x])continue ; int m=max (0LL ,x-a[i]); ne[m]=1 ; m=x^b[i]; ne[m]=1 ; } for (int j=0 ;j<2048 ;j++) dp[j]=ne[j]; } for (int i=2047 ;i>=0 ;i--) { if (dp[i]){ cout<<i; break ; } } } signed main () { int t=1 ; IOS while (t--) { solve (); } }
G 小L的散步 思路: 首先先来个起步检测,如果一开始就踩缝隙了,直接 YES,用前缀和数组+二分查找来进行之后的判断,用前缀和可以记录每个缝隙的位置,二分去找第一个大于后脚跟的缝隙,之后判断是否猜到缝隙。不要暴力,会超时。代码:
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 #include <bits/stdc++.h> using namespace std;#define int long long #define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0); #define endl '\n' const int N=2e5 +5 ;int a[N],b[N],s[N];void solve () { int n,m,l; cin>>n>>m>>l; s[0 ]=0 ; for (int i=1 ;i<=n;i++) { cin>>a[i]; s[i]=s[i-1 ]+a[i]; } for (int i=1 ;i<=m;i++) { cin>>b[i]; } if (l>a[1 ]) { cout<<"YES" ; return ; } int last=0 ; for (int i=1 ;i<=m;i++) { last+=b[i]; int le=1 ,r=n,j=-1 ; while (le<=r) { int mid=(le+r)/2 ; if (s[mid]>=last){ j=mid; r=mid-1 ; }else { le=mid+1 ; } } if (j!=-1 &&s[j]<last+l&&s[j]>last) { cout<<"YES" ; return ; } } cout<<"NO" ; } signed main () { int t=1 ; IOS while (t--) { solve (); } }
B 小L的彩球 思路: 要有 t 根线其实就是把这 n 个球分成 t+1 块,有两种情况,奇数块归左边或者是奇数块归右边。所以可以计算出左右两盒的块数,奇数块数在计算时需要上取整。然后其实就是在左边 x 个球中划分出 l 个块,就是 $C^{x-1}{l-1}, 右 边 是 C^{y-1} {r-1}$。反之同理。 组合数的计算可以等之后会发一篇简单数学。代码:
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 #include <bits/stdc++.h> using namespace std;#define int long long #define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0); #define endl "\n" const int MOD=998244353 ;const int N=1e6 +5 ;int fact[N],infact[N];int qmi (int a,int b) { int res=1 ; while (b) { if (b&1 ){ res=a*res%MOD; } b>>=1 ; a=a*a%MOD; } return res; } void pre () { fact[0 ]=infact[0 ]=1 ; for (int i=1 ;i<N;i++) { fact[i]=fact[i-1 ]*i%MOD; } infact[N-1 ]=qmi (fact[N-1 ],MOD-2 ); for (int i=N-2 ;i>=0 ;i--){ infact[i]=infact[i+1 ]*(i+1 )%MOD; } } int C (int n,int k) { if (k<0 ||k>n)return 0 ; return fact[n]*infact[k]%MOD*infact[n-k]%MOD; } void solve () { int n,x,t; cin>>n>>x>>t; if (t==0 ){ if (x==0 ||(n-x)==0 ){ cout<<"1" <<endl; }else cout<<"0" <<endl; return ; } int k=t+1 ; int ans=0 ; int l=(k+1 )/2 ,r=k/2 ; if (l<=x&&r<=n-x&&l>0 &&r>0 ){ ans=(ans+C (x-1 ,l-1 )*C (n-x-1 ,r-1 )%MOD)%MOD; } if (r<=x&&l<=n-x&&l>0 &&r>0 ){ ans=(ans+C (x-1 ,r-1 )*C (n-x-1 ,l-1 )%MOD)%MOD; } cout<<ans<<endl; } signed main () { IOS int T; cin>>T; pre (); while (T--) { solve (); } }
A 小L的三角尺 思路: 考察数学的,首先明确三角形的斜边长度是两直角边的平方和。 那么打磨后的斜边长为 ,对这个函数对 t 求导得 。 可以把这个看成一个单位贡献值,也就是打磨 1 单位长度后斜边减少多少。这个值随着 t 得增加而减少。 将这个单位贡献值从大到小进行排列,每次打磨一单位后重新计算。用优先队列来存储。 然后就是简单的计算了,最后一个循环把现在的斜边长计算出来。
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 #include <bits/stdc++.h> using namespace std;#define int long long #define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0); #define x first #define y second #define endl "\n" #define PII pair<double,int> const int N=5e5 +5 ;int a[N],b[N];double r[N];double cal (int i) { if (r[i]<=0 )return 0.0 ; else return r[i]/sqrt (1.0 *a[i]*a[i]+r[i]*r[i]); } void solve () { int n,w; cin>>n>>w; double sum=0 ; int total=0 ; int aa=0 ; for (int i=1 ;i<=n;i++) { cin>>a[i]>>b[i]; r[i]=b[i]; aa+=a[i]; total+=b[i]; sum+=sqrt (1.0 *a[i]*a[i]+1.0 *b[i]*b[i]); } if (w>=total){ cout<<fixed<<setprecision (9 )<<aa; return ; } priority_queue<PII> p; for (int i=1 ;i<=n;i++) { p.push ({cal (i*1LL ),i}); } while (w&&!p.empty ()) { auto [f,i]=p.top (); p.pop (); if (f=0 )break ; if (r[i]<=0 )continue ; w--; r[i]--; p.push ({cal (i*1LL ),i}); } double ans=0 ; for (int i=1 ;i<=n;i++) { ans+=sqrt (1.0 *a[i]*a[i]+r[i]*r[i]); } cout<<fixed<<setprecision (9 )<<ans; } signed main () { IOS int t=1 ; while (t--) { solve (); } }
🤔为什么把上一个题代码复制后总忘记改 N,罚时比我重写一遍都长。😭😭 看了 WIDA 的验题考虑后补 DE 吧