2024 Noip 做题记录(七)
个人训练赛题解(七)
Round #25 - 2024.10.23
A. [AGC010D] Divisor
题目大意
给定
,保证 。 两人轮流操作,每次给一个大于一的
减一,然后所有 约去 ,无法操作者输,求谁必胜。 数据范围:
。
思路分析
如果
此时先手必胜当且仅当
然后考虑一般的情况,如果偶数个数仍然为奇数,那么修改一个偶数,此时奇数个数
因此只要
否则考虑刚才的结果,如果此时奇数个数
时间复杂度
代码呈现
#include<bits/stdc++.h>
using namespace std;
const int MAXN=1e5+5;
int n,a[MAXN];
void solve(string A,string B) {
int s=0;
for(int i=1;i<=n;++i) s^=(a[i]-1)&1;
if(s) return cout<<A,void();
int o=0;
for(int i=1;i<=n;++i) {
if(a[i]==1) return cout<<B,void();
if(a[i]&1) {
if(o) return cout<<B,void();
o=i;
}
}
--a[o];
int g=a[1];
for(int i=2;i<=n;++i) g=__gcd(a[i],g);
for(int i=1;i<=n;++i) a[i]/=g;
solve(B,A);
}
signed main() {
ios::sync_with_stdio(false);
cin>>n;
for(int i=1;i<=n;++i) cin>>a[i];
solve("First\n","Second\n");
return 0;
}
B. [AGC011D] Reflect
题目大意
给定
个门,初始有开有关, 次操作从第一个门左侧扔一个球进去,如果一个门是开的,球会穿过,否则会被反弹,在此之后门会改变开关状态,求最终每个门的状态。 数据范围:
。
思路分析
如果第一个门是关的,会打开第一个门并结束,否则考虑整个过程:对于第
如果第
那么第
因此第一个门是开着的时,会将所有门翻转并循环左移一位。
那么维护当前的偏移量,可以
打表发现,经过
时间复杂度
代码呈现
#include<bits/stdc++.h>
using namespace std;
const int MAXN=2e5+5;
char s[MAXN];
signed main() {
int n,k;
scanf("%d%d%s",&n,&k,s);
k=min(k,4*n+(k&1));
int i=0;
while(k--) {
if(s[i%n]==(i&1?'B':'A')) s[i%n]^=3;
else ++i;
}
for(int j=i;j<i+n;++j) printf("%c",s[j%n]^(i&1?3:0));
return 0;
}
C. [AGC014E] Cut
题目大意
给定一棵
个点的树,每次选择一条边割掉,然后在两端连通块中选一个点,在第二棵树上连起来,求能否在第二棵树上构造出目标树。 数据范围:
。
思路分析
考虑第一条删除的边
因此一个朴素的做法就是把目标树上的边看成路径,覆盖在第一棵树上,每次取出被覆盖次数恰好
遇到多个覆盖次数
时间复杂度
代码呈现
#include<bits/stdc++.h>
using namespace std;
const int MAXN=1e5+5,inf=1e9;
int n,rk[MAXN],cov[MAXN];
struct ZkyGt1 {
static const int N=1<<17;
int tr[N<<1];
void psu(int p) {
int k=min(tr[p<<1],tr[p<<1|1]);
tr[p]+=k,tr[p<<1]-=k,tr[p<<1|1]-=k;
}
void init() {
for(int i=0;i<N;++i) tr[i+N]=(1<i&&i<=n?cov[rk[i]]:inf);
for(int i=N-1;i;--i) psu(i);
}
void add(int l,int r,int x) {
for(l+=N-1,r+=N+1;l^r^1;l>>=1,r>>=1) {
if(~l&1) tr[l^1]+=x;
if(r&1) tr[r^1]+=x;
psu(l>>1),psu(r>>1);
}
for(;l>1;l>>=1) psu(l>>1);
}
int qry() {
int p=1;
while(p<N) {
p<<=1;
if(tr[p]>tr[p^1]) p^=1;
}
tr[p]=inf;
for(int x=p;x>1;x>>=1) psu(x>>1);
return rk[p-N];
}
} T;
struct FenwickTree {
int tr[MAXN],s;
void add(int x,int v) { for(;x<=n;x+=x&-x) tr[x]^=v; }
int qry(int x) { for(s=0;x;x&=x-1) s^=tr[x]; return s; }
} Q;
int st[MAXN],ed[MAXN],siz[MAXN],dep[MAXN],fa[MAXN],hson[MAXN],top[MAXN],dfn[MAXN],dcnt;
vector <int> G[MAXN];
void dfs0(int u,int fz) {
siz[u]=1,dep[u]=dep[fz]+1,fa[u]=fz;
for(int v:G[u]) if(v^fz) {
dfs0(v,u),siz[u]+=siz[v];
if(siz[v]>siz[hson[u]]) hson[u]=v;
}
}
void dfs1(int u,int rt) {
top[u]=rt,dfn[u]=++dcnt,rk[dcnt]=u;
if(hson[u]) dfs1(hson[u],rt);
for(int v:G[u]) if(v!=fa[u]&&v!=hson[u]) dfs1(v,v);
}
int LCA(int u,int v) {
while(top[u]^top[v]) {
if(dep[top[u]]<dep[top[v]]) swap(u,v);
u=fa[top[u]];
}
return dep[u]<dep[v]?u:v;
}
void add(int u,int v,int k) {
while(top[u]^top[v]) {
if(dep[top[u]]<dep[top[v]]) swap(u,v);
T.add(dfn[top[u]],dfn[u],k),u=fa[top[u]];
}
if(dep[u]<dep[v]) swap(u,v);
if(u^v) T.add(dfn[v]+1,dfn[u],k);
}
void dfs3(int u) {
for(int v:G[u]) if(v^fa[u]) dfs3(v),cov[u]+=cov[v];
}
signed main() {
ios::sync_with_stdio(false);
cin>>n;
for(int i=1,u,v;i<n;++i) cin>>u>>v,G[u].push_back(v),G[v].push_back(u);
dfs0(1,0),dfs1(1,1);
for(int i=1;i<n;++i) {
cin>>st[i]>>ed[i];
Q.add(dfn[st[i]],i),Q.add(dfn[ed[i]],i);
++cov[st[i]],++cov[ed[i]];
cov[LCA(st[i],ed[i])]-=2;
}
dfs3(1),T.init();
for(int o=1;o<n;++o) {
if(T.tr[1]!=1) return puts("NO"),0;
int x=T.qry(),i=Q.qry(dfn[x]+siz[x]-1)^Q.qry(dfn[x]-1);
add(st[i],ed[i],-1);
Q.add(dfn[st[i]],i),Q.add(dfn[ed[i]],i);
}
puts("YES");
return 0;
}
D. [AGC012E] Camel
题目大意
数轴上有
个点 ,当前移动距离上限为 ,每次操作可以移动到距离当前点 的 上,或者令 后移动到任意一点上,对每个 求从当前点出发能否遍历所有点。 数据范围:
。
思路分析
容易发现瞬移操作最多进行
并且每次瞬移后会把当前点左侧和右侧距离
那么我们需要在
可以用 dp 解决,
要对每个起点求答案,相当于钦定了第一个集合中选择的线段,那么我们分别计算
求答案时枚举
时间复杂度
代码呈现
#include<bits/stdc++.h>
using namespace std;
const int MAXN=2e5+5;
int n,m,K,V[20],a[MAXN],lp[20][MAXN],rp[20][MAXN],f[1<<20],g[1<<20],t[MAXN];
signed main() {
scanf("%d%d",&n,&K);
for(int i=1;i<=n;++i) scanf("%d",&a[i]);
for(int i=K;i;i>>=1) V[m++]=i;
V[m++]=0;
for(int k=0;k<m;++k) {
lp[k][1]=1,rp[k][n]=n;
for(int i=2;i<=n;++i) lp[k][i]=(a[i]-a[i-1]>V[k])?i:lp[k][i-1];
for(int i=n-1;i;--i) rp[k][i]=(a[i+1]-a[i]>V[k])?i:rp[k][i+1];
}
for(int s=0;s<(1<<m);++s) {
f[s]=0,g[s]=n+1;
for(int i=0;i<m;++i) if(s>>i&1) {
f[s]=max(f[s],rp[i][f[s^(1<<i)]+1]);
g[s]=min(g[s],lp[i][g[s^(1<<i)]-1]);
}
}
int q=0;
for(int i=1;i<=n;++i) if(i==n||a[i+1]-a[i]>K) t[++q]=i;
if(q>m) {
for(int i=1;i<=n;++i) puts("Impossible");
return 0;
}
for(int i=1;i<=q;++i) {
int U=(1<<m)-2; bool ok=0;
for(int s=0;s<(1<<m);++s) if(!(s&1)&&t[i-1]<=f[s]&&g[U^s]<=t[i]+1) {
ok=1; break;
}
for(int j=t[i];j>t[i-1];--j) puts(ok?"Possible":"Impossible");
}
return 0;
}
*E. [AGC011F] Timetable
题目大意
给定
段铁路连接站点 ,每隔 时刻分别有一辆 和 的列车发车,穿过第 段铁路的时刻是 。 安排两种列车在每个站点停靠的时间,使得对于若干条特殊铁路,两种列车穿过其的时间不交,最小化两种列车运行时间之和。
数据范围:
。
思路分析
在
设
那么我们要求就是
展开后可以得到这相当于
目标是最小化
转移时
直接把 map
维护 dp 过程即可。
时间复杂度
代码呈现
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int MAXN=1e5+5;
const ll inf=1e18;
int n,m=0,p=0,K;
ll a[MAXN],L[MAXN],R[MAXN],w[MAXN*2];
map <int,ll> dp;
signed main() {
scanf("%d%d",&n,&K);
for(int i=1,op;i<=n;++i) {
scanf("%lld%d",&a[i],&op);
if(op==1&&2*a[i]>K) return puts("-1"),0;
a[i]+=a[i-1];
if(op==1) ++m,L[m]=(K-2*a[i-1]%K)%K,R[m]=(K-2*a[i]%K)%K,w[++p]=L[m],w[++p]=R[m];
}
sort(w,w+p+1),p=unique(w,w+p+1)-w;
for(int i=0;i<=p;++i) dp[i]=0;
for(int i=1;i<=m;++i) {
int l=lower_bound(w,w+p,L[i])-w;
int r=lower_bound(w,w+p,R[i])-w;
ll z=inf;
if(l<=r) {
auto il=dp.begin(),ir=dp.lower_bound(l);
for(auto it=il;it!=ir;++it) z=min(z,it->second+w[l]-w[it->first]);
dp.erase(il,ir);
il=dp.upper_bound(r),ir=dp.end();
for(auto it=il;it!=ir;++it) z=min(z,it->second+w[l]-w[it->first]+K);
dp.erase(il,ir);
} else {
auto il=dp.upper_bound(r),ir=dp.lower_bound(l);
for(auto it=il;it!=ir;++it) z=min(z,it->second+w[l]-w[it->first]);
dp.erase(il,ir);
}
if(dp.count(l)) dp[l]=min(dp[l],z);
else dp[l]=z;
}
ll ans=inf;
for(auto it:dp) ans=min(ans,it.second);
printf("%lld\n",ans+2*a[n]);
return 0;
}
*F. [AGC013F] Flip
题目大意
给定
个二元组 ,以及 个数 。 、
次独立询问,加入一个新的二元组 ,给每个二元组选择 ,并把他们和 两两匹配,要求 。最大化 的个数。 数据范围:
。
思路分析
先离散化使得
考虑如何判定一组
可以转化成给
不妨假设所有
可以采用朴素贪心,从前往后扫描所有
考虑优化,我们呢可以枚举每个询问选了
我们发现如果
那么我们可以先用一些操作使得所有
时间复杂度
代码呈现
#include<bits/stdc++.h>
using namespace std;
const int MAXN=1e5+5,inf=1e9;
int n,m,a[MAXN],b[MAXN],c[MAXN],qx[MAXN],qy[MAXN];
int rv,f[MAXN],tg[MAXN],dp[MAXN],nxt[MAXN];
vector <int> op[MAXN];
bool st[MAXN];
void solve1() {
priority_queue <array<int,2>,vector<array<int,2>>,greater<array<int,2>>> q;
for(int i=n,s=0;i>=1;--i) {
s+=tg[i];
for(int o:op[i]) q.push({b[o],o});
while(s+f[i]<-1) {
while(q.size()&&q.top()[0]>i) q.pop();
if(q.empty()) {
for(int j=1;j<=m;++j) puts("-1");
exit(0);
}
int z=q.top()[1]; q.pop();
st[z]=true,++rv,++s,++tg[a[z]-1],--tg[b[z]-1];
}
}
}
void solve2() {
priority_queue <array<int,2>> q;
for(int i=1,s=0;i<=n;++i) {
s+=tg[i],dp[i+1]=dp[i];
for(int o:op[i]) q.push({a[o]-1,o});
if(s+f[i]<0) {
while(q.size()&&q.top()[0]<i) q.pop();
if(q.empty()) {
for(int j=i+1;j<=n+1;++j) dp[j]=inf;
return ;
}
int z=q.top()[1]; q.pop();
++dp[i+1],++s,++tg[b[z]],--tg[a[z]];
}
}
}
signed main() {
scanf("%d",&n),++n;
for(int i=1;i<n;++i) scanf("%d%d",&a[i],&b[i]);
for(int i=1;i<=n;++i) scanf("%d",&c[i]),f[i]=-1;
sort(c+1,c+n+1);
scanf("%d",&m);
for(int i=1,x,y;i<=m;++i) {
scanf("%d%d",&x,&y);
qx[i]=lower_bound(c+1,c+n+1,x)-c;
qy[i]=lower_bound(c+1,c+n+1,y)-c;
}
for(int i=1;i<n;++i) {
a[i]=lower_bound(c+1,c+n+1,a[i])-c;
b[i]=lower_bound(c+1,c+n+1,b[i])-c;
b[i]=min(a[i],b[i]),++f[a[i]];
if(a[i]>b[i]) op[a[i]-1].push_back(i);
}
for(int i=1;i<=n;++i) f[i]+=f[i-1];
solve1();
for(int i=n;i>=1;--i) tg[i]+=tg[i+1],f[i]+=tg[i];
for(int i=1;i<=n;++i) op[i].clear();
for(int i=1;i<n;++i) if(!st[i]&&a[i]>b[i]) op[b[i]].push_back(i);
memset(tg,0,sizeof(tg));
solve2();
for(int i=1;i<=m;++i) printf("%d\n",max({-1,n-rv-dp[qx[i]],n-rv-dp[qy[i]]-1}));
return 0;
}
*G. [AGC014F] Localmax
题目大意
给定
排列 ,每次操作会把所有 LocalMax 按顺序放到序列末尾,求多少次操作后序列被排好序。 数据范围:
。
思路分析
我们发现整个排列中性质最好的元素就是
因此我们先假设已知值域为
假设将值域
如果
否则我们需要判断操作
考虑进行
那么我们可以取出此时的序列开头
我们发现在操作过程中,如果
由于操作次数有限,因此取出最后的一个时刻满足
是非开头 LocalMax,那么操作后 的前一个元素 也应该是原序列的 LocalMax。 那么由于
最终要变成序列开头,因此在此之后必然存在一次操作不同时移动 ,此时 又变成非开头 LocalMax,矛盾。
然后通过分类讨论
倒序枚举,不断从值域
时间复杂度
代码呈现
#include<bits/stdc++.h>
using namespace std;
const int MAXN=2e5+5;
int n,a[MAXN],p[MAXN];
signed main() {
scanf("%d",&n);
for(int i=1;i<=n;++i) scanf("%d",&a[i]),p[a[i]]=i;
int f=0,x=0;
for(int i=n-1;i;--i) {
if(!f) {
if(p[i]<p[i+1]);
else ++f,x=i+1;
} else {
if((p[x]<p[i]&&p[i]<p[i+1])||(p[i]<p[i+1]&&p[i+1]<p[x])||(p[i+1]<p[x]&&p[x]<p[i]));
else ++f,x=i+1;
}
}
printf("%d\n",f);
return 0;
}
Round #26 - 2024.10.29
A. [AGC015D] Or
题目大意
在
的元素中选出一个子集 ,求 中元素按位或有多少种不同取值。 数据范围:
。
思路分析
首先
对于
此时设
那么我们把元素分成
如果不选第一部分的元素,那么能得到的元素就是
取出这两部分元素的并,并且和
时间复杂度:
代码呈现
#include<bits/stdc++.h>
#define ll long long
using namespace std;
int d(ll x) { return x?63-__builtin_clzll(x):-1; }
signed main() {
ll A,B;
scanf("%lld%lld",&A,&B);
if(A==B) return puts("1"),0;
ll ans=B-A+1,i=d(A^B),S=(1ll<<i)-1;
A&=S,B&=S;
if(d(A)<=d(B)) ans+=S-B;
else ans+=S-A+(1ll<<(d(B)+1))-B;
printf("%lld\n",ans);
return 0;
}
B. [AGC015E] Car
题目大意
给定
个动点,第 个动点从 出发以 的速度移动,初始给若干个动点染色,两个动点相遇后,如果有一个染色点,会给另一个点也染色。 求有多少种初始染色方案,使得最终每个点都被染色。
数据范围:
。
思路分析
设
观察
因此一条染色路径是斜率
观察发现每个点可以染色的点是横坐标连续的一段区间,即
那么给一个点染色相当于选择一个区间,要求所有区间的并为
用
时间复杂度
代码呈现
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int MAXN=2e5+5,MOD=1e9+7;
struct Node { int x,v; } a[MAXN];
ll f[MAXN],s[MAXN];
int n,l[MAXN],r[MAXN];
vector <int> op[MAXN];
signed main() {
scanf("%d",&n);
for(int i=1;i<=n;++i) scanf("%d%d",&a[i].x,&a[i].v);
sort(a+1,a+n+1,[&](auto i,auto j){ return i.v<j.v; });
map <int,int> q;
for(int i=1,t=0;i<=n;++i) {
if(a[i].x>t) q[t=a[i].x]=i;
l[i]=q.lower_bound(a[i].x)->second;
}
q.clear();
for(int i=n,t=MOD;i>=1;--i) {
if(a[i].x<t) q[t=a[i].x]=i;
r[i]=(--q.upper_bound(a[i].x))->second;
op[r[i]].push_back(l[i]);
}
f[0]=s[0]=1;
for(int i=1;i<=n;++i) {
s[i]=s[i-1];
sort(op[i].begin(),op[i].end());
for(int k:op[i]) {
f[i]=(f[i]+s[i]+MOD-(k>1?s[k-2]:0))%MOD;
s[i]=(s[i-1]+f[i])%MOD;
}
}
printf("%lld\n",f[n]);
return 0;
}
C. [AGC017F] Path
题目大意
给定
杨辉三角,选出 条折线,每条折线在每一层都要从左到右升序排列。 还有
个限制形如第 个折线第 层必须向下 / 向右下,求方案数。 数据范围:
。
思路分析
考虑类似轮廓线 dp 的想法,
但此时我们还需要额外记录第
考虑优化,我们发现两条折线取值不同当且仅当某一行第
因此这种情况发生后,在第
因此我们可以把这条折线的下一次向右下方移动提前到当前位置上来,这样第
然后进行 dp 即可,用位运算优化状态转移即可。
时间复杂度
代码呈现
#include<bits/stdc++.h>
using namespace std;
const int MOD=1e9+7;
inline void add(int &x,const int &y) { x=(x+y>=MOD)?x+y-MOD:x+y; }
int lim[25][25],f[1<<20],g[1<<20];
signed main() {
int n,m,q;
scanf("%d%d%d",&n,&m,&q),--n;
for(int i=0;i<m;++i) for(int j=0;j<n;++j) lim[i][j]=-1;
for(int x,y,z;q--;) scanf("%d%d%d",&x,&y,&z),lim[x-1][y-1]=z;
f[0]=1;
for(int i=0;i<m;++i) for(int j=0;j<n;++j) {
memset(g,0,sizeof(g));
for(int s=0;s<(1<<n);++s) {
if(lim[i][j]!=1) if(!(s>>j&1)) add(g[s],f[s]);
if(lim[i][j]!=0) {
if(s>>j&1) add(g[s],f[s]);
else {
int o=s>>j; if(o) o&=o-1;
add(g[((o|1)<<j)|(s&((1<<j)-1))],f[s]);
}
}
}
memcpy(f,g,sizeof(f));
}
int ans=0;
for(int s=0;s<(1<<n);++s) add(ans,f[s]);
printf("%d\n",ans);
return 0;
}
*D. [AGC019E] Shuffle
题目大意
给定两个长度为
的 01 串 , 的个数相同,记为 。 随机排列
,然后依次交换 ,求最终 的概率。 数据范围:
。
思路分析
我们先考虑将
假设我们已经知道所有
用有向边连接所有
环上的每个点
我们发现每个点是什么状态实际是由
那么假设只有出度 / 入度的点有
那么图上会包含
设
- 如果加入一条链,那么选择两个端点,转移
。 - 如果在链中间加入一个中转点,插入在某条链的末尾,转移
。
计算答案的时候枚举链上“中转点”个数,剩余的环随便连:
时间复杂度
代码呈现
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int MAXN=10005,MOD=998244353;
ll ksm(ll a,ll b=MOD-2) { ll s=1; for(;b;a=a*a%MOD,b>>=1) if(b&1) s=s*a%MOD; return s; }
char a[MAXN],b[MAXN];
int n,m,len;
ll ans,f[MAXN],fac[MAXN],ifac[MAXN];
signed main() {
for(int i=fac[0]=ifac[0]=1;i<MAXN;++i) ifac[i]=ksm(fac[i]=fac[i-1]*i%MOD);
scanf("%s%s",a+1,b+1),len=strlen(a+1);
for(int i=1;i<=len;++i) if(a[i]=='1') b[i]=='1'?++m:++n;
f[0]=1;
for(int i=1;i<=n;++i) {
for(int j=0;j<=m;++j) f[j]=f[j]*(n-i+1)*(n-i+1)%MOD;
for(int j=1;j<=m;++j) f[j]=(f[j]+f[j-1]*i*(m-j+1))%MOD;
}
for(int j=0;j<=m;++j) {
ans=(ans+f[m-j]*fac[n+m]%MOD*ifac[n+m-j]%MOD*fac[j])%MOD;
}
printf("%lld\n",ans);
return 0;
}
*E. [AGC018F] Subtree
题目大意
给定
个点的有根树 ,给每个点赋权值,使得两棵树上每个点的子树权值和都是 。 数据范围:
。
思路分析
很显然每个点的权值的奇偶性和其儿子个数有关,如果两棵树上儿子个数奇偶性不同,一定无解。
可以猜测当每个点的权值取
此时我们相当于每个点的子树中,和为
这种题可以考虑用欧拉回路构造。
用一个虚根连接两棵树的根,方便处理每个节点。
此时度数为偶数的节点有奇数个儿子,权值一定取
我们把这种度数为奇数的节点在两棵树上对应的点连起来,此时每个点度数为偶数,求出一条欧拉回路。
我们定义一个点的权值为
此时
时间复杂度
代码呈现
#include<bits/stdc++.h>
using namespace std;
const int MAXN=2e5+5;
struct Edge { int v,id; };
vector <Edge> G[MAXN];
int n,ec=0,fx[MAXN],fy[MAXN],cur[MAXN],ans[MAXN];
bool vis[MAXN*2];
void link(int x,int y) {
++ec,G[x].push_back({y,ec}),G[y].push_back({x,ec});
}
void dfs(int u) {
for(int &i=cur[u];i<(int)G[u].size();++i) if(!vis[G[u][i].id]) {
Edge e=G[u][i];
vis[e.id]=true,dfs(e.v);
if(e.v==u+n) ans[u]=1;
else if(u==e.v+n) ans[e.v]=-1;
}
}
signed main() {
scanf("%d",&n);
for(int i=1;i<=n;++i) {
scanf("%d",&fx[i]);
link(~fx[i]?fx[i]:0,i);
}
for(int i=1;i<=n;++i) {
scanf("%d",&fy[i]);
link(~fy[i]?fy[i]+n:0,i+n);
}
for(int i=1;i<=n;++i) if(G[i].size()%2!=G[i+n].size()%2) return puts("IMPOSSIBLE"),0;
puts("POSSIBLE");
for(int i=1;i<=n;++i) if(G[i].size()%2) link(i,i+n);
dfs(0);
for(int i=1;i<=n;++i) printf("%d ",ans[i]);
puts("");
return 0;
}
*F. [AGC015F] Euclid
题目大意
定义
,对于所有 的数对求 的最大值,以及有多少 取到最大值。 数据范围:
。
思路分析
设
这是简单的,取到最大值的
那么我们就是要找所有
我们发现如果
发现
然后考虑逆推生成,发现在
并且还有额外的一个元素对
那么元素对个数是
时间复杂度
代码呈现
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int MAXN=105,MOD=1e9+7;
ll fib[MAXN];
vector <array<ll,2>> f[MAXN];
signed main() {
const int n=88;
fib[0]=fib[1]=1;
for(int i=2;i<=n;++i) fib[i]=fib[i-1]+fib[i-2];
f[1]={{1,2}};
for(int i=2;i<=n;++i) {
for(auto x:f[i-1]) f[i].push_back({x[1],x[0]+x[1]});
f[i].push_back({fib[i+1],fib[i-1]+fib[i+1]});
}
int T; scanf("%d",&T);
for(ll x,y;T--;) {
scanf("%lld%lld",&x,&y);
if(x>y) swap(x,y);
int i=1; ll c=0;
while(fib[i+1]<=x&&fib[i+2]<=y) ++i;
for(auto o:f[i]) {
if(o[0]<=x&&o[1]<=y) c=(c+(y-o[1])/o[0]+1)%MOD;
if(o[1]<=x&&o[0]<=y) c=(c+(x-o[1])/o[0]+1)%MOD;
}
if(i==1) c=(c+x)%MOD;
printf("%d %lld\n",i,c);
}
return 0;
}
*G. [AGC020F] Arc
题目大意
给定一个周长为
的环,有 条长度为 的弧,每条弧均匀随机一个实数位置放置,求所有弧覆盖整个环至少一次的概率。 数据范围:
。
思路分析
先从弧的位置是整点的情况入手:我们需要从一个合适的位置进行破环为链。
破环为链的一个缺陷是如果某个弧的起点
但我们可以从最长链
因此对于这种弧我们就不需要考虑越过
然后考虑取的是实数的情况。
事实上我们只关心
因此我们可以直接枚举
时间复杂度
代码呈现
#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll dp[305][64],ans=0;
int n,m,a[10],p[10];
signed main() {
scanf("%d%d",&n,&m);
for(int i=0;i<n;++i) scanf("%d",&a[i]),p[i]=i;
sort(a,a+n);
do {
memset(dp,0,sizeof(dp));
dp[a[n-1]*n][0]=1;
for(int i=1;i<=n*m;++i) if(i%n) {
int x=p[i%n-1];
for(int j=i;j<=n*m;++j) for(int s=0;s<(1<<(n-1));++s) if(!(s>>x&1)) {
dp[min(n*m,max(j,i+a[x]*n))][s|1<<x]+=dp[j][s];
}
}
ans+=dp[n*m][(1<<(n-1))-1];
} while(next_permutation(p,p+n-1));
long double z=ans;
for(int i=1;i<n;++i) z/=i;
for(int i=1;i<n;++i) z/=m;
printf("%.20Lf\n",z);
return 0;
}
Round #27 - 2024.10.31
A. [AGC024E] Insert
题目大意
从空序列开始,依次向序列中插入一个
的元素,插入 次,要求字典序单调递增,求方案数。 数据范围:
。
思路分析
考虑对最终的序列 dp 删除元素的顺序,删除
涉及元素大小关系的问题可以插入 dp,每次考虑插入最小值,值域从
考虑第一个
那么
那么
时间复杂度
代码呈现
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int MAXN=305;
ll f[MAXN][MAXN],C[MAXN][MAXN];
signed main() {
int n,m,MOD;
scanf("%d%d%d",&n,&m,&MOD);
for(int i=0;i<MAXN;++i) for(int j=C[i][0]=1;j<=i;++j) C[i][j]=(C[i-1][j]+C[i-1][j-1])%MOD;
f[0][0]=1;
for(int i=1;i<=m;++i) {
memcpy(f[i],f[i-1],sizeof(f[i]));
for(int j=1;j<=n;++j) for(int k=0;k<j;++k) {
f[i][j]=(f[i][j]+f[i-1][k]*f[i][j-k-1]%MOD*C[j][j-k])%MOD;
}
}
printf("%lld\n",f[m][n]);
return 0;
}
*B. [AGC023D] Vote
题目大意
给定数轴上
个点,第 个点有 个人在公交上,每个人要到对应的点上下车。 当前公交在
,每个时刻所有人投票决定公交向左还是向右,选票多的方向(平票向左)。 每个人都向最小化到目标的时间,求最终运行时间。
数据范围:
。
思路分析
考虑哪个点最后访问,很显然是第
对
考虑
因此路径最后一步一定是
所以
注意如果
时间复杂度
代码呈现
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int MAXN=1e5+5;
int n,s;
ll a[MAXN],x[MAXN];
ll f(int l,int r,int op) {
if(s<x[l]) return x[r]-s;
if(x[r]<s) return s-x[l];
if(a[l]<a[r]) return a[r]+=a[l],f(l+1,r,1)+(op!=1?x[r]-x[l]:0);
else return a[l]+=a[r],f(l,r-1,0)+(op!=0?x[r]-x[l]:0);
}
signed main() {
scanf("%d%d",&n,&s);
for(int i=1;i<=n;++i) scanf("%lld%lld",&x[i],&a[i]);
printf("%lld\n",f(1,n,-1));
return 0;
}
*C. [AGC024F] Sequence
题目大意
给定若干长度
的 01 串,求一个 01 串至少是其中 个串的子序列,且长度最长,同长度字典序最小。 数据范围:
。
思路分析
可以考虑计算出每个 01 串
一个比较复杂的问题是如何让每个串恰好计算一次,可以考虑用子序列自动机进行判定。
对每个串建子序列自动机,
转移就是
我们可以发现
时间复杂度
代码呈现
#include<bits/stdc++.h>
using namespace std;
int n,K,f[21][1<<21],g[1<<21];
int hb(int x) { return 31-__builtin_clz(x); }
void add(int x,int i,int y,int w) { f[i][x<<i|y]+=w; }
signed main() {
cin>>n>>K;
for(int i=0;i<=n;++i) for(int s=0;s<(1<<i);++s) {
char op; cin>>op;
if(op=='1') ++f[i][1<<i|s];
}
for(int i=n;~i;--i) for(int s=0;s<(1<<(n+1));++s) if(f[i][s]) {
int x=s>>i,y=s&((1<<i)-1);
g[x]+=f[i][s];
if(y) {
int j=hb(y);
add(x<<1|1,j,y&((1<<j)-1),f[i][s]);
}
if(y!=(1<<i)-1) {
int j=hb(y^((1<<i)-1));
add(x<<1,j,y&((1<<j)-1),f[i][s]);
}
}
for(int i=n;i>=1;--i) for(int s=0;s<(1<<i);++s) if(g[1<<i|s]>=K) {
for(int o=i-1;~o;--o) cout<<(s>>o&1);
cout<<"\n";
return 0;
}
cout<<"\n";
return 0;
}
*D. [AGC021E] Box
题目大意
给定
个蓝色盒子,顺次加入 个红或蓝色的球,每个球选择一个盒子放入,如果该盒子中当前颜色的球严格多于另一种颜色的球,那么盒子会变成这种颜色。 求有多少种球的颜色序列使得存在至少一种放盒子的方案使得每个盒子最终为红色。
数据范围:
。
思路分析
枚举红球和蓝球个数
一个盒子最终为红色,要么红球个数比蓝球多,要么两者相等且最后一次插入的是蓝球。
因此
如果
此时
因此此时只会有
其次,我们发现一个红蓝球个数相等的盒子,如果红蓝球个数
因此所有红蓝球个数相等的盒子中,只有一个红球一个蓝球。
那么我们把红球看成左括号,蓝球看成右括号,要满足的限制就是序列的最大括号匹配
把括号序列看成
展开得到
时间复杂度
代码呈现
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int MAXN=5e5+5,MOD=998244353;
ll fac[MAXN],ifac[MAXN],ans;
ll ksm(ll a,ll b=MOD-2) { ll s=1; for(;b;a=a*a%MOD,b>>=1) if(b&1) s=s*a%MOD; return s; }
ll C(int x,int y) {
if(x<0||y<0||y>x) return 0;
return fac[x]*ifac[y]%MOD*ifac[x-y]%MOD;
}
signed main() {
for(int i=fac[0]=ifac[0]=1;i<MAXN;++i) ifac[i]=ksm(fac[i]=fac[i-1]*i%MOD);
int n,K;
scanf("%d%d",&n,&K);
if(K<n) return puts("0"),0;
for(int R=(K+1)/2;R<=K;++R) {
int B=K-R; if(R==B) --B;
ans=(ans+C(R+B,R)+MOD-C(R+B,n-R+B-1))%MOD;
}
printf("%lld\n",ans);
return 0;
}
*E. [AGC022D] Shuttle
题目大意
给定
个商场位于 ,在商场 需要停留至少 时刻,一辆车在 之间以 的速度来回往返,经过商场的时候可以上下车,求遍历所有商场后回到起点的最小用时。 数据范围:
。
思路分析
首先整个过程以
我们发现朴素的做法就是在每个
考虑如何优化:这个过程中车在
我们发现有的时候只要车在
因此记
考虑如何减少折返轮次,首先一次折返经过每个点两次,因此一轮折返最多经过两个点。
那么我们肯定是在
然后求出最大匹配即可。
进一步观察发现,一个
因此不存在形如
按顺序维护贪心即可。
注意特殊情况如:
时间复杂度
代码呈现
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int MAXN=3e5+5;
int n,st[MAXN],tp;
ll a[MAXN],t[MAXN],L,ans;
bool l[MAXN],r[MAXN],vis[MAXN];
signed main() {
scanf("%d%lld",&n,&L),ans=n+1;
for(int i=1;i<=n;++i) scanf("%lld",&a[i]);
for(int i=1;i<=n;++i) {
scanf("%lld",&t[i]),ans+=t[i]/(2*L),t[i]%=2*L;
l[i]=(2*a[i]>=t[i]),r[i]=(2*(L-a[i])>=t[i]);
}
if(r[n]) --ans;
for(int i=1;i<n;++i) if(!t[i]) --ans,vis[i]=true;
for(int i=1,hd=1,tl=0;i<n;++i) {
if(l[i]&&r[i]&&!vis[i]) st[++tl]=i;
if(!l[i]&&r[i]&&hd<=tl) --ans,vis[st[hd++]]=true;
}
tp=0;
for(int i=n-1,hd=1,tl=0;i;--i) {
if(l[i]&&r[i]&&!vis[i]) st[++tl]=i;
if(l[i]&&!r[i]&&hd<=tl) --ans,vis[st[hd++]]=true;
}
int c=0;
for(int i=1;i<n;++i) c+=l[i]&&r[i]&&!vis[i];
ans-=c>>1;
printf("%lld\n",2*L*ans);
return 0;
}
Round #28 - 2024.11.04
A. [AGC025D] Grid
题目大意
给定
,在 的网格中选 个点使得任意两个点之间的距离不为 或 。 数据范围:
。
思路分析
设
:说明 为奇数,因此距离为 的点横坐标奇偶性不同。 :说明 恰有一个奇数,因此距离为 的点黑白间隔染色后颜色不同。 :说明 均为偶数,将整个网格按横纵坐标 分成四个完全相等的部分。
因此我们发现距离为
那么距离为
这是简单的,在两张二分图上黑白染色,如果两个点在两张二分图上颜色都相同就划入同一个等价类,可以把
时间复杂度
代码呈现
#include<bits/stdc++.h>
using namespace std;
const int MAXN=605;
int n,k1,k2;
void col(auto a,int k) {
int x=0;
while(k%4==0) k>>=2,++x;
if(k%4==1) {
for(int i=0;i<n;++i) for(int j=0;j<n;++j) a[i][j]=((i>>x)+(j>>x))&1;
} else if(k%4==2) {
for(int i=0;i<n;++i) for(int j=0;j<n;++j) a[i][j]=i>>x&1;
}
}
bool f[MAXN][MAXN],g[MAXN][MAXN];
signed main() {
scanf("%d%d%d",&n,&k1,&k2),n*=2;
col(f,k1),col(g,k2);
for(int p:{0,1}) for(int q:{0,1}) {
vector <array<int,2>> wys;
for(int i=0;i<n;++i) for(int j=0;j<n;++j) {
if(f[i][j]==p&&g[i][j]==q) wys.push_back({i,j});
}
if(wys.size()>=n*n/4) {
wys.resize(n*n/4);
for(auto z:wys) printf("%d %d\n",z[0],z[1]);
return 0;
}
}
return 0;
}
B. [AGC027D] Mod
题目大意
给定
,构造 矩阵,使得所有元素 且两两不同。 且对于任意相邻元素
, 都相等且 。 数据范围:
。
思路分析
一个朴素想法是对整个矩阵黑白间隔染色,然后在黑格上全填质数,白格填周围四个数的乘积
但这样要太多质数,一个更好的办法是给每行每列赋一个质数,黑格取所在行列质数乘积,白格填周围四个数的
不难想到对于每条对角线赋一个质数,黑格取所在两条对角线质数乘积,白格周围就只剩下了四个质数。
时间复杂度
代码呈现
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int MAXN=505,MAXV=10005;
bool isc[MAXV];
vector <int> pr;
ll a[MAXN][MAXN];
ll lcm(ll x,ll y) { return (__int128)x/__gcd(x,y)*y; }
signed main() {
for(int i=2;i<MAXV;++i) {
if(!isc[i]) pr.push_back(i);
for(int p:pr) {
if(i*p>=MAXV) break;
isc[i*p]=true;
if(i%p==0) break;
}
}
int n,op=0;
scanf("%d",&n);
if(n==2) return puts("4 7\n23 10"),0;
int L=0,R=2*n-1+(n&1);
auto val=[&](){ return (op^=1)?pr[L++]:pr[--R]; };
for(int i=0;i<=n+1;++i) for(int j=0;j<=n+1;++j) a[i][j]=1;
for(int i=1;i<=n;i+=2) for(int x=1,y=i,p=val();y>=1;++x,--y) a[x][y]*=p;
for(int i=2+(n&1);i<=n;i+=2) for(int x=i,y=n,p=val();x<=n;++x,--y) a[x][y]*=p;
for(int i=n-1+(n&1);i>=1;i-=2) for(int x=1,y=i,p=val();y<=n;++x,++y) a[x][y]*=p;
for(int i=3;i<=n;i+=2) for(int x=i,y=1,p=val();x<=n;++x,++y) a[x][y]*=p;
for(int i=1;i<=n;++i) for(int j=1;j<=n;++j) if((i+j)&1) {
a[i][j]=lcm(lcm(a[i-1][j],a[i+1][j]),lcm(a[i][j-1],a[i][j+1]))+1;
}
for(int i=1;i<=n;++i,puts("")) for(int j=1;j<=n;++j) printf("%lld ",a[i][j]);
return 0;
}
C. [AGC026E] Pair
题目大意
给定
个 a,b
构成的字符串,每次可以把从左往右的第个 a
和b
同时删除,求能得到的字典序最大的串。数据范围:
。
思路分析
考虑从后往前 dp,设 a
和 b
得到的最大字典序串。
设 a
或 b
的位置。
很显然可以直接删除
否则如果保留了 b
和 a
。
那么我们肯定不会保留这部分的 a
,直接找到第一个
否则 b
和 a
,很显然这些 b
一定是选择了更优,然后我们又会选若干 b
继续选上,不断递归直到 a
,从
时间复杂度
代码呈现
#include<bits/stdc++.h>
using namespace std;
const int MAXN=6005;
int n,id[MAXN],a[MAXN],b[MAXN];
char s[MAXN];
string f[MAXN];
signed main() {
scanf("%d%s",&n,s+1);
for(int i=1,x=0,y=0;i<=n*2;++i) {
if(s[i]=='a') a[id[i]=++x]=i;
else b[id[i]=++y]=i;
}
for(int i=n;i>=1;--i) {
if(a[i]<b[i]) {
int j=i+1;
for(;j<=n&&min(a[j],b[j])<=b[i];++j);
f[i]=max("ab"+f[j],f[i+1]);
} else {
int j=b[i];
for(;j<=n*2&&b[id[j]]<a[id[j]]&&(id[j]<=i||b[id[j]]<a[id[j]-1]);++j) {
if(id[j]>=i) f[i]+=s[j];
}
f[i]=max(f[i]+f[id[j]],f[i+1]);
}
}
printf("%s\n",f[1].c_str());
return 0;
}
D. [AGC027F] Link
题目大意
给定两棵
个点的树 ,对于每个点 可以在 上改变一个叶子的父亲(每个 操作至多一次)。 求让
的最小操作次数。 数据范围:
。
思路分析
假设操作次数
此后
设两棵树上
并且对于一个要操作的
那么所有
时间复杂度
代码呈现
#include<bits/stdc++.h>
using namespace std;
const int MAXN=55;
int n,deg[MAXN],ind[MAXN],fa[MAXN],fb[MAXN];
bool w[MAXN];
vector <int> G[MAXN];
vector <array<int,2>> A,B;
void dfs(int u,int *f) { for(int v:G[u]) if(v^f[u]) f[v]=u,dfs(v,f); }
int sol(int rt) {
for(int i=1;i<=n;++i) G[i].clear();
for(auto e:A) G[e[0]].push_back(e[1]),G[e[1]].push_back(e[0]);
fa[rt]=0,dfs(rt,fa);
for(int i=1;i<=n;++i) G[i].clear();
for(auto e:B) G[e[0]].push_back(e[1]),G[e[1]].push_back(e[0]);
fb[rt]=0,dfs(rt,fb);
for(int i=1;i<=n;++i) G[i].clear(),ind[i]=0;
int s=0; w[rt]=0;
for(int i=1;i<=n;++i) if(i^rt) w[i]=fa[i]^fb[i],s+=w[i];
for(int i=1;i<=n;++i) {
if(!w[i]&&w[fa[i]]) return n+1;
if(w[i]&&w[fa[i]]) G[i].push_back(fa[i]),++ind[fa[i]];
if(w[i]&&w[fb[i]]) G[fb[i]].push_back(i),++ind[i];
}
queue <int> q;
for(int i=1;i<=n;++i) if(!ind[i]) q.push(i);
while(q.size()) {
int u=q.front(); q.pop();
for(int v:G[u]) if(!--ind[v]) q.push(v);
}
for(int i=1;i<=n;++i) if(ind[i]) return n+1;
return s;
}
void solve() {
scanf("%d",&n),A.resize(n-1),B.resize(n-1);
for(int i=1;i<=n;++i) deg[i]=0;
for(auto &e:A) {
scanf("%d%d",&e[0],&e[1]),++deg[e[0]],++deg[e[1]];
if(e[0]>e[1]) swap(e[0],e[1]);
}
for(auto &e:B) {
scanf("%d%d",&e[0],&e[1]);
if(e[0]>e[1]) swap(e[0],e[1]);
}
sort(A.begin(),A.end());
sort(B.begin(),B.end());
if(A==B) return puts("0"),void();
int ans=n+1;
for(auto &e:A) {
int u=e[0],v=e[1];
if(deg[u]==1) {
for(int i=1;i<=n;++i) if(i!=u&&i!=v) e={u,i},ans=min(ans,sol(u)+1);
}
if(deg[v]==1) {
for(int i=1;i<=n;++i) if(i!=u&&i!=v) e={i,v},ans=min(ans,sol(v)+1);
}
e={u,v};
}
printf("%d\n",ans>n?-1:ans);
}
signed main() {
int T; scanf("%d",&T);
while(T--) solve();
return 0;
}
*E. [AGC025E] Direct
题目大意
给定
个点的树和 条路径,给每条路径定向,一条边 如果被沿 或 方向经过,分别产生 的收益,最大化收益。 数据范围:
。
思路分析
假设每条边被覆盖次数为
考虑构造,我们实际上可以将这个条件强化为沿
可以发现在树上随意移动,如果最终回到原点,那么每条边沿两种方向经过的次数一定相同。
那么一个朴素的想法是对每条路径连接起点和终点,求出欧拉回路后按欧拉回路定向,此时每条边两种方向经过次数相同。
问题是这张图不一定有欧拉回路,可以调整,对于每个度数为奇数的点
由于初始所有点度数总和为偶数,因此这样总能调整出解,并且每条树边至多被添加一次,删去这些树边后,两种方向的经过次数差就
时间复杂度
代码呈现
#include<bits/stdc++.h>
using namespace std;
const int MAXN=2005;
int n,m;
vector <int> G[MAXN];
int dfn[MAXN],st[MAXN][20],dcnt;
int cmp(int x,int y) { return dfn[x]<dfn[y]?x:y; }
int bit(int x) { return 1<<x; }
int LCA(int x,int y) {
if(x==y) return x;
int l=min(dfn[x],dfn[y])+1,r=max(dfn[x],dfn[y]),k=__lg(r-l+1);
return cmp(st[l][k],st[r-bit(k)+1][k]);
}
void dfs0(int u,int fz) {
dfn[u]=++dcnt,st[dcnt][0]=fz;
for(int v:G[u]) if(v^fz) dfs0(v,u);
}
int d[MAXN],s[MAXN],t[MAXN],ans=0;
struct Edge { int v,id; };
vector <Edge> E[MAXN];
void dfs1(int u,int fz) {
for(int v:G[u]) if(v^fz) dfs1(v,u),d[u]+=d[v];
ans+=min(d[u],2);
if(E[u].size()&1) {
E[u].push_back({fz,u+m});
E[fz].push_back({u,u+m});
}
}
bool vis[MAXN*2];
int cur[MAXN];
void eul(int u) {
for(int &i=cur[u];i<(int)E[u].size();++i) if(!vis[E[u][i].id]) {
auto e=E[u][i];
vis[e.id]=true,eul(e.v);
if(e.id<=m&&u!=s[e.id]) swap(s[e.id],t[e.id]);
}
}
signed main() {
scanf("%d%d",&n,&m);
for(int i=1,u,v;i<n;++i) {
scanf("%d%d",&u,&v);
G[u].push_back(v),G[v].push_back(u);
}
dfs0(1,0);
for(int k=1;k<=20;++k) for(int i=1;i+bit(k)-1<=n;++i) {
st[i][k]=cmp(st[i][k-1],st[i+bit(k-1)][k-1]);
}
for(int i=1;i<=m;++i) {
scanf("%d%d",&s[i],&t[i]);
++d[s[i]],++d[t[i]],d[LCA(s[i],t[i])]-=2;
E[s[i]].push_back({t[i],i});
E[t[i]].push_back({s[i],i});
}
dfs1(1,0);
for(int i=1;i<=n;++i) eul(i);
printf("%d\n",ans);
for(int i=1;i<=m;++i) printf("%d %d\n",s[i],t[i]);
return 0;
}
*F. [AGC025F] And
题目大意
给定两个
位二进制数 ,每次操作同时给 加上 ,求 次操作后的结果。 数据范围:
。
思路分析
朴素的做法就是模拟
但这样做不好优化,观察到单次操作中,后面的
因此对于
即找到
对于每个
没有进位当且仅当
时间复杂度
代码呈现
#include<bits/stdc++.h>
using namespace std;
const int MAXN=2e6+5;
int a[MAXN],b[MAXN],stk[MAXN],tp;
signed main() {
int n,m,K;
scanf("%d%d%d",&n,&m,&K);
for(int i=n;i;--i) scanf("%1d",&a[i]);
for(int i=m;i;--i) scanf("%1d",&b[i]);
stk[0]=MAXN-1;
for(int i=max(n,m);i;--i) {
vector <int> nw;
for(int j=i,c=K;;) {
nw.push_back(j);
while(stk[tp]<=j) --tp;
if(a[j]>1||b[j]>1) {
a[j+1]+=a[j]>>1,a[j]&=1;
b[j+1]+=b[j]>>1,b[j]&=1;
++j;
} else if(a[j]&&b[j]&&c) {
int p=min(stk[tp],c+j);
a[j]=b[j]=0,++a[p],++b[p],c-=p-j,j=p;
} else break;
}
reverse(nw.begin(),nw.end());
for(int o:nw) if(a[o]||b[o]) stk[++tp]=o;
}
for(n=MAXN-1;!a[n];--n);
for(int i=n;i;--i) printf("%d",a[i]); puts("");
for(m=MAXN-1;!b[m];--m);
for(int i=m;i;--i) printf("%d",b[i]); puts("");
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 一文读懂知识蒸馏
· 终于写完轮子一部分:tcp代理 了,记录一下