USACO 2022 February contest
Cu
忘存代码了,看个乐就行。
T1 Sleeping in Class
给出 \(n\) 个数 \(a\),任意合并相邻两个数,问使合并到最后全部相等的合并次数最小值。
\(n\le 10^5,\sum a \le 10^6\)
因为合并到最后的数一定是 \(\sum a\) 的约数,所以枚举 \(\sum a\) 很少的约数然后 \(O(n)\) 判断即可。Orz huaruoji。
因为我没有注意到 \(\sum a\) 的范围,所以我直接暴力枚举第一个数合并到的位置,同样的判断。但加了个优化,如果答案比当前位置合并所花次数还小就 break。
\(O(n*玄学)\)。
T2 Photoshoot 2
给出两个排列,一次操作可以把第一个排列中的一个数任意左移,求最小操作次数把第一个排列变成第二个排列。
首先把第二个排列当做 \(12345\)。注意到一次操作只能左移,所以要把第一个排列的 \(5\) 归位,位置在 \(5\) 右边的数全都要动,我们发现因为这些数是任意动,所以它们一定可以在左边排好后依次插入,所以我们就只需要看左边的。这样有点像递归,但实际上,我们只需要从大到小枚举数的位置,维护之前最靠左的位置,如果新枚举到的在维护位置的右边就不用管了,把新枚举到的数与维护的位置中间的数计入操作次数并把当前位置作为新的最靠左的位置。
\(O(n)\) 即可。
T3 Blocks
随便dfs一下就行。
Ag
T1 Redistributing Gifts
没做出来,思路到了设 \(dp[i][j]\) 为 \(i\) 能够在让其他牛都开心的同时拿到 \(j\),然后转移就是枚举 \(k\),
\(dp[i][j]\|=dp[i][k]\&(grk[j][k]<=grk[j][j])\)
\(dp[i][j]\|=dp[k][j]\&(grk[k][i]<=grk[k][k])\)
然后我魔改了一下floyd,结果WA了。。。
点击查看代码
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
rk[i][j]=in,grk[i][rk[i][j]]=j;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
mp[i][j]=(grk[j][i]<=grk[j][j]);
for(int k=1;k<=n;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
mp[i][j]|=(mp[k][j]&(grk[k][i]<=grk[k][k])),
mp[i][j]|=(mp[i][k]&(grk[j][k]<=grk[j][j]));
有木有路过的大佬能把这个思路继续下去的。
T2 Robot Instructions
感觉比T1好做。
就是把40个操作分成两半,每一半分别 \(2^{20}\) 枚举,第二部分在第一部分里找可以组合起来的。
这里如果用二分找要记得只二分一遍,不然会T。
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define in read()
inline int read(){
int p=0,f=1;
char c=getchar();
while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
while(isdigit(c)){p=p*10+c-'0';c=getchar();}
return p*f;
}
const int N=1100000;
struct node{
int x,y,stp,num;
bool operator<(const node a){
return x!=a.x?x<a.x:y!=a.y?y<a.y:stp<a.stp;
}
bool operator>(const node a){
return x>a.x||(x==a.x&&(y>a.y||(y==a.y&&stp>a.stp)));
}
bool operator==(const node a){
return x==a.x&&y==a.y&&stp==a.stp;
}
}e[N];
int en;
int n,X,Y;
int tx[45],ty[45];
inline void dfs1(int u,int sx,int sy,int ss){
if(u==n/2+1){
e[++en].x=sx,e[en].y=sy,e[en].stp=ss,e[en].num=1;
return ;
}
dfs1(u+1,sx,sy,ss);
dfs1(u+1,sx+tx[u],sy+ty[u],ss+1);
}
inline int bin(node q){
int l=1,r=en,mid;
while(l<r){
mid=(l+r)>>1;
if(e[mid]>q||e[mid]==q)r=mid;
else l=mid+1;
}
return l;
}
int ans[N];
inline void dfs2(int u,int sx,int sy,int ss){
if(u==n+1){
int q=bin({X-sx,Y-sy,0,0});
while(e[q].x==X-sx&&e[q].y==Y-sy){
ans[e[q].stp+ss]+=e[q].num;
q++;
}
return ;
}
dfs2(u+1,sx,sy,ss);
dfs2(u+1,sx+tx[u],sy+ty[u],ss+1);
}
signed main(){
n=in,X=in,Y=in;
for(int i=1;i<=n;i++)
tx[i]=in,ty[i]=in;
dfs1(1,0,0,0);
sort(e+1,e+1+en);
int ten=0;
for(int i=1;i<=en;i++)
if(e[i].x^e[i-1].x||e[i].y^e[i-1].y||e[i].stp^e[i-1].stp)
e[++ten].x=e[i].x,e[ten].y=e[i].y,e[ten].stp=e[i].stp;
else e[ten].num++;
en=ten;
dfs2(n/2+1,0,0,0);
for(int i=1;i<=n;i++)
cout<<ans[i]<<'\n';
return 0;
}
T3 Email Filing
没做。