The 49th ICPC Asia Regionals Online Contest (II) VP记录
前言
几个世纪不写博客了,上一篇还是在三月,写完便进入了持续的摆烂中,如今暑期集训即将结束,杭电牛客全部打完,终于能稍微闲下来一丢丢了,今日无组队赛,和队友VP去年网络赛第二场,心血来潮,遂写题解。
F-Tourist
致敬tourist的小小签到,遍历数组维护当前分值,达到4000输出下标并退出即可。
J-Stacking of Goods
签到题,贪心地考虑每个物品的属性,尝试最大化每个物品被压缩的体积\(\Delta V_i=c_i\sum_{j=1}^{i-1}W_j\)
考虑排序的标准:对于任意两个相邻物品 \(item_i\) 与 \(item_{i+1}\),显然二者的码放顺序对二者上方其他物体以及下方其他物体产生的贡献相同,故仅考虑二者因顺序不同产生的局部贡献的差异,即比较
\(c_i\sum_{j=1}^{i-1}W_j+c_{i+1}\sum_{j=1}^{i}W_j\) 与 \(c_{i+1}\sum_{j=1}^{i-1}W_j+c_{i}(\sum_{j=1}^{i-1}W_j+W_{i+1})\)的大小
整理后易得如下结论:
AC代码:
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define llu long long unsigned int
#define db double
#define endl '\n'
#define PII pair<ll,ll>
const ll inf=0x3f3f3f3f;
const ll mod=1e9+7;
const ll nn=2e5+5;
const ll mm=3e5+5;
const ll kk=20;
const ll INF=1e18;
/*
char *p1,*p2,buf[100000];
#define nc() (p1==p2 && (p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++)
int read()
{
int x=0,f=1;
char ch=nc();
while(ch<48||ch>57)
{
if(ch=='-')
f=-1;
ch=nc();
}
while(ch>=48&&ch<=57)
x=x*10+ch-48,ch=nc();
return x*f;
}
*/
/*
void write(int x)
{
if(x<0)
putchar('-'),x=-x;
if(x>9)
write(x/10);
putchar(x%10+'0');
return;
}
*/
struct node{
ll x,y,z;
};
void solve()
{
ll n;cin>>n;
vector<node>v(n+1);
for(ll i=1;i<=n;i++)
{
ll x,y,z;cin>>x>>y>>z;
v[i]=(node){x,y,z};
}
sort(v.begin()+1,v.end(),[](node x,node y)->bool
{
return x.z*y.x<y.z*x.x;
});
ll now=0,ans=0;
for(ll i=1;i<=n;i++)
{
ans+=v[i].y-v[i].z*now;
now+=v[i].x;
}
cout<<ans<<endl;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr),cout.tie(nullptr);
ll tt=1;
//tt=read();
//cin>>tt;
while(tt--)
solve();
return 0;
}
I-Strange Binary
特殊的二进制分解,增加了不能出现连续\(0\)位的约束,但每位的取值范围下界扩展到了\(-1\),自然容易想到通过形如 \(a_{i-1}=-1,a_{i}=1\) 的构造方法避免第\(i\)位和第\(i+1\)位出现连续的\(0\),注意特判\(n\)被\(4\)整除的情况
AC代码:
点击查看代码
#include<bits/stdc++.h>
#define N 1600006
#define mod 998244353
#define int long long
using namespace std;
int read()
{
char a=getchar();
int b=0,d=1;
while(a<'0'||a>'9')
{
if(a=='-')
d*=-1;
a=getchar();
}
while(a>='0'&&a<='9')
b=(b<<3)+(b<<1)+a-'0',a=getchar();
return b*d;
}
int n;
int ans[66];
signed main()
{
int T=read();
while(T--)
{
n=read();
if(!(n%4))
{
printf("NO\n");
continue;
}
printf("YES\n");
for(int i=0;i<32;++i)
ans[i]=n%2,n>>=1;
for(int i=1;i<31;++i)
if(ans[i]==0&&ans[i+1]==0)
ans[i]=ans[i-1],ans[i-1]*=-1;
for(int i=0;i<4;++i)
{
for(int j=0;j<8;++j)
printf("%lld ",ans[i*8+j]);
printf("\n");
}
}
return 0x0;
}
L-502 Bad Gateway
难绷的求期望,一开始想到了预处理一个递推,然而脑子糊涂了没注意到1e9的数据量,随后队友给出了临界点思路:不妨设操作与否的临界点为\(a\),则期望\(E=\sum_{i=1}^a\frac{i}{T}+\frac{(1+E)(T-a)}{T}\)
即\(E=\frac{(a+1)}{2}+\frac{(T-a)}{a}\), 求导得\(E'=\frac{1}{2}-\frac{T}{a^2}\)
令导数等于零,求得临界点\(a=\sqrt{2T}\),代入原式即可
AC代码:
点击查看代码
#include<bits/stdc++.h>
#define N 1600006
#define mod 998244353
#define int long long
using namespace std;
int read()
{
char a=getchar();
int b=0,d=1;
while(a<'0'||a>'9')
{
if(a=='-')
d*=-1;
a=getchar();
}
while(a>='0'&&a<='9')
b=(b<<3)+(b<<1)+a-'0',a=getchar();
return b*d;
}
int n;
int gcd(int x,int y)
{
return y ? gcd(y,x%y):x;
}
signed main()
{
int T=read();
while(T--)
{
n=read();
if(n==1)
{
printf("%lld %lld\n",1ll,1ll);
continue;
}
int a=sqrt(2*n);
int son1=a*a+2*n-a,mom1=2*a;
++a;
int son2=a*a+2*n-a,mom2=2*a;
if(son1*mom2>son2*mom1)
{
int now=gcd(son2,mom2);
printf("%lld %lld\n",son2/now,mom2/now);
}
else
{
int now=gcd(son1,mom1);
printf("%lld %lld\n",son1/now,mom1/now);
}
// else if(!(n%2))
// {
// int a=n/2;
// int son=a*a+5*a,mom=n+2;
// int now=gcd(son,mom);
// printf("%lld %lld\n",son/now,mom/now);
// }
// else
// {
// int a=n/2;
// int son=a*a+5*a+2,mom=a*2+2;
// int now=gcd(son,mom);
// printf("%lld %lld\n",son/now,mom/now);
// }
}
return 0x0;
}
G-Game
思路非常直接:不存在输家给赢家钱的情况,遂直接考虑\(x\)和\(y\)的辗转相除,涵盖所有的Alice获胜情况,就是代码难写,又逆元又求和,头疼
AC代码:
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define llu long long unsigned int
#define db double
#define endl '\n'
#define PII pair<ll,ll>
const ll inf=0x3f3f3f3f;
const ll mod=998244353;
const ll nn=2e5+5;
const ll mm=3e5+5;
const ll kk=20;
const ll INF=1e18;
/*
char *p1,*p2,buf[100000];
#define nc() (p1==p2 && (p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++)
int read()
{
int x=0,f=1;
char ch=nc();
while(ch<48||ch>57)
{
if(ch=='-')
f=-1;
ch=nc();
}
while(ch>=48&&ch<=57)
x=x*10+ch-48,ch=nc();
return x*f;
}
*/
/*
void write(int x)
{
if(x<0)
putchar('-'),x=-x;
if(x>9)
write(x/10);
putchar(x%10+'0');
return;
}
*/
ll qpow(ll x,ll y)
{
ll res=1;
while(y)
{
if(y&1)res=(res*x)%mod;
x=(x*x)%mod;
y>>=1;
}
return res%mod;
}
void solve()
{
ll x,y;cin>>x>>y;
ll a0,a1,b;cin>>a0>>a1>>b;
ll val=(a0+a1)%mod,invs=qpow(val,mod-2);
ll fac=a0*invs%mod,rval=a1*invs%mod;
bool a00=(a0==0);
ll A=0,F=1,xx=x,yy=y;
while(xx>0&&yy>0)
{
if(a00)
{
if(xx>=yy)xx%=yy;
else{
F=0;
break;
}
}
else{
if(xx>=yy)
{
ll k=xx/yy,xxmod=xx%yy,rk=qpow(rval,k);
ll term1=0;
if(rval!=1)
{
ll denom=(1-rval+mod)%mod,geom=(1-rk+mod)%mod;
geom=geom*qpow(denom,mod-2)%mod;
term1=fac*geom%mod;
}
A=(A+F*term1)%mod;
F=F*rk%mod;
xx=xxmod;
}
else{
ll k=yy/xx,fack=qpow(fac,k);
F=F*fack%mod;
yy%=xx;
}
}
}
ll ba=(yy==0)?1:0,ans=(A+F*ba)%mod;
ans=(ans%mod+mod)%mod;
cout<<ans<<endl;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr),cout.tie(nullptr);
ll tt=1;
//tt=read();
cin>>tt;
while(tt--)
solve();
return 0;
}
A-Gambling on Choosing Regionals
开局牢秦认为此题签到,然因题面又臭又长又绕未被采信,做完上述题目再来看,发现果真不难,痛心疾首,但即便如此,仍有思路上的啸问题:起初牢秦自信认为只需考虑最大的\(c_i\),后发现样例都处理不了,重新思考后发现完全想反了,二人接力sort大法T两发(绷),后发现按学校考虑最坏可达\(O(n^2)\),调整思路为桶排后AC,此时已是3小时12分,后E题试图挣扎但无果,结束战斗
AC代码:
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define llu long long unsigned int
#define db double
#define endl '\n'
#define PII pair<ll,ll>
const ll inf=0x3f3f3f3f;
const ll mod=1e9+7;
const ll nn=2e5+5;
const ll mm=3e5+5;
const ll kk=20;
const ll INF=1e18;
/*
char *p1,*p2,buf[100000];
#define nc() (p1==p2 && (p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++)
int read()
{
int x=0,f=1;
char ch=nc();
while(ch<48||ch>57)
{
if(ch=='-')
f=-1;
ch=nc();
}
while(ch>=48&&ch<=57)
x=x*10+ch-48,ch=nc();
return x*f;
}
*/
/*
void write(int x)
{
if(x<0)
putchar('-'),x=-x;
if(x>9)
write(x/10);
putchar(x%10+'0');
return;
}
*/
void solve()
{
ll n,k;cin>>n>>k;
ll mx=INF;
for(ll i=1;i<=k;i++)
{
ll x;cin>>x;
mx=min(mx,x);
}
map<string,ll>mp;
map<ll,ll>ma;
vector<pair<string,ll>>v(n+1);
vector<ll>ans(n+1);
for(ll i=1;i<=n;i++)
{
ll x;cin>>x;
string s;cin>>s;
v[i]={s,x};
mp[s]++;
ma[x]=i;
}
ll tmp=0;
for(auto i=mp.begin();i!=mp.end();i++)
{
tmp+=min(mx,i->second);
}
sort(v.begin()+1,v.end(),[](pair<string,ll> x,pair<string,ll> y)->bool
{
return x.second<y.second;
});
for(ll i=1;i<=n;i++)
{
tmp-=min(mp[v[i].first],mx);
mp[v[i].first]--;
int now=tmp+min(mp[v[i].first],mx-1);
tmp+=min(mp[v[i].first],mx);
ans[ma[v[i].second]]=now+1;
}
for(int i=1;i<(ll)ans.size();++i)
cout<<ans[i]<<'\n';
/*for(ll i=1;i<=n;i++)
{
ll ans=0;
for(auto j=mp.begin();j!=mp.end();j++)
{
ll l=0,r=j->second.size()-1,mid=0;
while(l<r)
{
mid=(l+r)>>1;
if(j->second[mid]>v[i].second)r=mid;
else l=mid+1;
}
ans+=min(mx,(ll)j->second.size()-r);
}
cout<<ans<<endl;
}
for(auto i=mp.begin();i!=mp.end();i++)
{
for(ll j=0;j<(ll)i->second.size();j++)
cout<<i->second[j]<<" ";
cout<<endl;
}*/
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr),cout.tie(nullptr);
ll tt=1;
//tt=read();
//cin>>tt;
while(tt--)
solve();
return 0;
}
特别鸣谢:
队友牢秦:qinchengxin
队友小沈:diddadida001
对I、J、A的思路提供和代码编写

浙公网安备 33010602011771号