前言
牛客三场 pta三场 pta缺了一场 还没补完
补题主要补了牛客的题
天梯赛的题还要再补一补
牛客
2026牛客寒假算法基础集训营4
真白的幻觉
当时没搞懂
在十进制下,目前已知的最大乘法持续性是 11,达到这个值的最小数是 277777788888899(15 位,小于 1018),另一个数 277777899999999999(18 位,小于 1018)也具有乘法持续性 11,并且它的 f(x) 与前者不同。
cpp
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define inf 0x3f3f3f3f3f
//#define modd 1e9+7
#define PII pair<int,int>
void solve() {
cout << "27777789999999999 277777788888899";
}
signed main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int lll=1;
// cin>>lll;
while(lll--){
solve();
// cout<<'\n';
}
return 0;
}
2026牛客寒假算法基础集训营5
智乃的果子
一开始写的优先队列没过
遵循哈夫曼树的核心规则(每次合并重量最小的两堆),保证总代价最小;
对同重量的多个堆做 "两两批量合并",奇数个同重量堆时,剩余 1 个堆和下一个最小堆合并,保证所有堆最终合并为 1 个,且终止条件(只剩 1 个堆)正确。
cpp
#include <bits/stdc++.h>
using namespace std;
#define int long long
int mod = 1e9 + 7;
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int n;
cin >> n;
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> q;
for (int i = 1; i <= n; i++)
{
int c, w;
cin >> c >> w;
q.push({w, c});
}
int ans = 0;
while (1)
{
auto u = q.top();
q.pop();
if (q.empty() && u.second == 1)
break;
int w = u.first, c = u.second;
int k = c / 2;
if (k)
{
int a = 2 * w % mod * (k % mod) % mod;
ans = (ans + a) % mod;
q.push({w * 2, k});
}
if (c & 1)
{
auto u2 = q.top();
q.pop();
ans = (ans + (w + u2.first) % mod) % mod;
q.push({w + u2.first, 1});
if (u2.second > 1)
q.push({u2.first, u2.second - 1});
}
}
cout << ans << endl;
}
智乃的最大子段和取模
将子段和取模问题可以转化为前缀和之差取模的问题。
对于每个新的前缀和,在已有的前缀和中寻找能使差值取模最大的那个,使用set来维护前缀和,使用了lower_bound ,通过检查邻近元素来确保找到最优解。
cpp
#include <bits/stdc++.h>
using namespace std;
#define ull unsigned long long
#define int long long
#define pii array<int,2>
#define endl "\n"
void solve() {
int n, mod;
cin >> n >> mod;
vector<int> a(n+9), s(n+9);
for (int i = 1; i <= n; i++) cin >> a[i];
for (int i = 1; i <= n; i++) s[i] = (s[i-1]+a[i]) % mod;
int ans = 0, L = 1, R = 1;
auto cal = [&](int l, int r) {
if ((s[r]-s[l-1]+mod)%mod > ans) {
ans = (s[r]-s[l-1]+mod)%mod;
L = l, R = r;
}
};
set<pii> st;
st.insert({0, 1});
for (int i = 1; i <= n; i++) {
for (int x = 0; x <= 2; x++) {
auto it = st.lower_bound({s[i] - (mod-1) + x*mod, n+1});
if (it == st.end()) --it;
for (int j = 1; j <= 5; j++) {
cal((*it)[1], i);
if (it == st.begin()) it = prev(st.end());
else --it;
}
}
st.insert({s[i], i+1});
}
cout << L-1 << " " << R-1 << " " << ans << endl;
}
signed main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int t = 1;
for (int i = 0; i < t; i++) {
solve();
}
return 0;
}
2026牛客寒假算法基础集训营6
小L的三角尺
贪心 + 优先队列(大根堆)
每次都选择当前能获得最大收益的那一次打磨操作,这样就能在有限的 w 次打磨中,让总斜边长度减少得最多,从而得到最小的总和。
cpp
#include <bits/stdc++.h>
using namespace std;
#define ull unsigned long long
#define int long long
#define pii array<int,2>
#define endl "\n"
double dis(int x, int y) {
return sqrtl(x*x+y*y);
}
void solve() {
int n, w;
cin >> n >> w;
priority_queue<pair<double, pii>> pq;
double ans = 0;
for (int i = 1; i <= n; i++) {
int x, y;
cin >> x >> y;
double d = dis(x,y) - dis(x,y-1);
pii tmp = {x,y};
pq.push(make_pair(d, tmp));
ans += dis(x,y);
}
while (w--) {
if (pq.empty()) break;
auto [d, tmp] = pq.top();
pq.pop();
ans -= d;
auto [x, y] = tmp;
y--;
if (y == 0) continue;
d = dis(x,y) - dis(x,y-1);
tmp = {x,y};
pq.push(make_pair(d, tmp));
}
cout << fixed << setprecision(10) << ans << endl;
}
signed main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int t = 1;
for (int i = 0; i < t; i++) {
solve();
}
return 0;
}
小L的彩球
组合计数问题 用"隔板法" 模型
cpp
#include<bits/stdc++.h>
#define int long long
#define endl '\n'
#define mod 998244353
using namespace std;
int n,x,t,y;
int jc[1000009];
int jcinv[1000009];
int ksm(int x,int y)
{
int res=1;
while(y>0){
if(y&1){
res=(res*x)%mod;
}
x=(x*x)%mod;
y/=2;
}
return res;
}
void inv()
{
jc[0]=1;
for(int i=1;i<=1000005;i++){
jc[i]=jc[i-1]*i%mod;
}
jcinv[1000005]=ksm(jc[1000005],mod-2);
for(int i=1000004;i>=0;i--){
jcinv[i]=jcinv[i+1]*(i+1)%mod;
}
}
int C(int x,int y)
{
if(x<0||y<0||y>x) return 0;
return jc[x]*jcinv[x-y]%mod*jcinv[y]%mod;
}
void solve()
{
cin>>n>>x>>t;
y=n-x;
if(t==0){
if(x==n||y==n)
cout<<"1"<<endl;
else
cout<<"0"<<endl;
return;
}
int ans=1;
if(t&1){
int ptr=(t+1)/2;
ans=ans*C(x-1,ptr-1)%mod*C(y-1,ptr-1)%mod;
ans=ans*2%mod;
}else{
ans--;
int ptr=t/2;
ans=(ans+C(x-1,ptr-1)*C(y-1,ptr)%mod)%mod;
ans=(ans+C(x-1,ptr)*C(y-1,ptr-1)%mod)%mod;
}
cout<<ans<<endl;
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
int T;
cin>>T;
inv();
while(T--)solve();
return 0;
}
pta
估值一亿的AI核心代码
cpp
#include <bits/stdc++.h>
using namespace std;
int judge(char c)
{
if((c>='A'&&c<='Z')||(c>='a'&&c<='z'))
return 1;
else if(c>='0'&&c<='9')
return 2;
else if(c==' ')
return 0;
else
return -1;
}
string AI(string ask)
{
while(ask[0]==' ')
ask.erase(ask.begin());
while(ask[ask.size()-1]==' ')
ask.erase(ask.end()-1);
for(int i=0;i<ask.size();i++)
{
if(ask[i]>='A'&&ask[i]<='Z'&&ask[i]!='I')
ask[i]+=32;
if(ask[i]=='?')
ask[i]='!';
if(ask[i]==' ')
{
int j=i+1;
while(ask[j]==' ') j++;
ask.erase(ask.begin()+i+1,ask.begin()+j);
}
}
for(int i=0;i<ask.size();i++)
{
if(i==0)
{
if(ask[i]=='I'&&(judge(ask[i+1])<=0||i+1==ask.size()))
ask.replace(i,1,"you");
else if(ask.substr(i,2)=="me"&&(judge(ask[i+2])<=0||i+2==ask.size()))
ask.replace(i,2,"you");
else if(ask.substr(i,7)=="can you"&&(judge(ask[i+7])<=0||i+7==ask.size()))
ask.replace(i,7,"I can");
else if(ask.substr(i,9)=="could you"&&(judge(ask[i+9])<=0||i+9==ask.size()))
ask.replace(i,9,"I could");
}
if(judge(ask[i])<=0)
{
if(judge(ask[i+1])==1)
{
if(ask[i+1]=='I'&&(judge(ask[i+2])<=0||i+2==ask.size()))
ask.replace(i+1,1,"you");
if(ask.substr(i+1,2)=="me"&&(judge(ask[i+3])<=0||i+3==ask.size()))
ask.replace(i+1,2,"you");
if(ask.substr(i+1,7)=="can you"&&(judge(ask[i+8])<=0||i+8==ask.size()))
ask.replace(i+1,7,"I can");
if(ask.substr(i+1,9)=="could you"&&(judge(ask[i+10])<=0||i+10==ask.size()))
ask.replace(i+1,9,"I could");
}
}
}
return ask;
}
int main()
{
int n;
string ask,ans;
cin>>n;
cin.get();
while(n--)
{
getline(cin,ask);
cout<<ask<<endl;
ans=AI(ask);
cout<<"AI: ";
for(int i=0;i<ans.size();i++)
{
if(ans[i]==' '&&judge(ans[i+1])<=0)
continue;
else
cout<<ans[i];
}
cout<<endl;
}
return 0;
}
病毒溯源
cpp
#include <bits/stdc++.h>
using namespace std;
#define ull unsigned long long
#define int long long
#define pii array<int,2>
#define endl "\n"
vector<int> t[10010];
vector<int> ans, path;
void dfs(int rt){
if(t[rt].size() == 0){
if(path.size() > ans.size() ||(path < ans && path.size() == ans.size())) ans = path;
return ;
}
for(int i = 0; i < t[rt].size(); i++){
path.push_back(t[rt][i]);
dfs(t[rt][i]);
path.pop_back();
}
}
void solve() {
int N, rt;
cin >> N;
rt = (0 + N - 1) * N / 2;
for(int i = 0; i < N; i++){
int K;
cin >> K;
for(int j = 0; j < K; j++){
int v;
cin >> v;
rt -= v;
t[i].push_back(v);
}
}
dfs(rt);
cout << ans.size() + 1 << endl << rt;
for(int i = 0; i < ans.size(); i++){
cout << " " << ans[i];
}
}
signed main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int t = 1;
for (int i = 0; i < t; i++) {
solve();
}
return 0;
}