The 2022 ICPC Asia Hangzhou Regional Programming Contest (partial)
The 2022 ICPC Asia Hangzhou Regional Programming Contest - Codeforces
省流:自己打的vp,但是在应该会做的简单数论和DP上疯狂挂分,唐完了。
最后没打过一群学弟,紫砂了。
建议我和大一组一队让我混个Au
同学和大一组一队,感觉要让他白捡Au了
Tag
字符串哈希,数论,DP,字典树
F
签到,暴力判断每个字符串中是否有"bie",把符合条件的进行字符串hash存储在哈希表(unordered_set)里。
int n;
typedef unsigned long long ull;
unordered_set<ull> mp;
const int base=10000007;
int main(){
ios::sync_with_stdio(0);cin.tie(0);
cin>>n;
for(int i=1;i<=n;i++){
int m;
cin>>m;
int f=1;
for(int j=1;j<=m;j++){
string s;
cin>>s;
for(unsigned k=2;k<s.size();k++){
if(s[k-2]=='b'&&s[k-1]=='i'&&s[k]=='e'){
ull hash=0;
for(unsigned p=0;p<s.size();p++)
hash=hash*base+s[p];
if(mp.find(hash)==mp.end()){
f=0;
cout<<s<<endl;
mp.insert(hash);
}
break;
}
}
}
if(f){
cout<<"Time to play Genshin Impact, Teacher Rice!"<<endl;
}
}
return 0;
}
D
找规律题,写了个暴力后发现最终答案形式一定为$2x,x,x ,… ,x$。
吓死了,差点智商又被强奸了
int n,a[100005];
int main(){
R(n);
double sum=0;
for(int i=1;i<=n;i++){
R(a[i]);
sum+=a[i];
}
double k=sum/(n+1);
printf("%.8lf",k*2);
for(int i=2;i<=n;i++)
printf(" %.8lf",k);
return 0;
}
A
根据等差数列求和公式可知$$sum=\sum_{i=1}^{n}a_i+ns + \frac{n(n+1)}{2}d $$
题意即$$ns + \frac{n(n+1)}{2}d+\sum_{i=1}^{n}a_i\equiv c(mod \,m)$$
求任意一种s和d满足c最小。
令$g=gcd(n,\frac{n(n+1)}{2})$由裴蜀定理得$$nx+\frac{n(n+1)}{2}y = g$$的解$x_{1},y_{1}$。
我们只需要再求出$$gx+my=gcd(g,m)$$的解$x_{2},y_{2}$。
令$$k=\left \lfloor \frac{\sum_{i=1}^{n}a_i}{gcd(g,m)}\right \rfloor$$
那么,$$min{c}=\sum_{i=1}^{n}a_i-(k \times gcd(g,m))$$ $$s=x_1 x_2 k$$ $$d=y_1 x_2 k$$
这里要注意,我们要求$s$和$d$均为非负整数且小于$m$,然而我当时犯唐受经典题的影响试图用$ax+by\equiv c(mod \,m)$
的最小正整数解公式$x=(x\%(b/g)+(b/g))\%(b/g)$
,但是这样并不能保证$y$也在范围内。最后发现只要两个值都进行$x=(x\%m+m)\%m$
就解决了,属实唐完了
int n,m,a[100005];
void exgcd(int &x,int &y,int &g,int a,int b)
{
if(!b)
{
x=1;
y=0;
g=a;
return;
}
exgcd(x,y,g,b,a%b);
int t=x;
x=y;
y=t-a/b*y;
}
signed main(){
R(n);R(m);
int sum=0;
for(int i=1;i<=n;i++){
R(a[i]);
sum+=a[i];
}
sum%=m;
int x1,y1,g1;
exgcd(x1,y1,g1,n,n*(n+1)/2);
x1=(x1%m+m)%m;
y1=(y1%m+m)%m;
int x2,y2,g2;
exgcd(x2,y2,g2,g1,m);
x2=(x2%(m)+(m))%(m);
int k=-sum/g2;
x1=(x1*k%m*x2%m+m)%m;
y1=(y1*k%m*x2%m+m)%m;
printf("%lld\n",sum+k*g2);
printf("%lld %lld\n",x1,y1);
return 0;
}
C
发现"only a part of the item will be upgraded"这种情况只可能发生在最后一件可以使用的物品上。除此之外,对于任何使用的物品,使用顺序是无关紧要的。
所以改变物品的使用顺序相当于考虑每件物品取或不取,实际上可以转化成01背包问题。
那么我们正向做一遍01背包,反向做一遍01背包,再枚举最后一件使用的物品是什么,把结果拼起来即可。
特别地,当$\sum p_i \le k$时,我们直接全部选取即可。
int n,K;
int p[3005],w[3005][11];
int f[3005][3005],ff[3005][3005];
const int inf=-1e16;
signed main(){
R(n);R(K);
int sum=0;
for(int i=1;i<=n;i++){
R(p[i]);
for(int j=1;j<=p[i];j++){
R(w[i][j]);
}
sum+=p[i];
}
int ans=0;
if(sum<=K){
for(int i=1;i<=n;i++){
ans+=w[i][p[i]];
}
printf("%lld\n",ans);
return 0;
}
for(int i=0;i<=n+1;i++)
for(int j=0;j<=K;j++)
f[i][j]=ff[i][j]=inf;
f[0][0]=ff[n+1][0]=0;
for(int i=1;i<=n;i++){
for(int j=0;j<p[i];j++) f[i][j]=f[i-1][j];
for(int j=p[i];j<=K;j++)
f[i][j]=max(f[i-1][j],f[i-1][j-p[i]]+w[i][p[i]]);
}
for(int i=n;i>=1;i--){
for(int j=0;j<p[i];j++) ff[i][j]=ff[i+1][j];
for(int j=p[i];j<=K;j++)
ff[i][j]=max(ff[i+1][j],ff[i+1][j-p[i]]+w[i][p[i]]);
}
for(int i=1;i<=n;i++)
for(int k=1;k<=p[i];k++)
for(int j=0;j<=K-k;j++)
ans=max(ans,f[i-1][j]+ff[i+1][K-k-j]+w[i][k]);
printf("%lld\n",ans);
return 0;
}
以下是Satori5ama在做这题时的唐氏操作:
- dp数组没清成inf
- 正向dp数组设成inf了没设置反向dp数组inf
- 反向dp转移方程直接copy正向dp,然后忘了把i-1改成i+1
- 没有特判$\sum p_i \le k$
- 把$w_{i,j}$当成$p_i$加到$sum$里然后查半天查不出来,
最后重写了一遍过了
K
参考:The 2022 ICPC Asia Hangzhou Regional Programming Contest - Luckyblock - 博客园 (cnblogs.com)
挂因是估错大小了,f和ans没开long long
int n,q;
string s;
int ch[2000005][26],tot=1;
long long f[26][26],siz[2000005],cnt[2000005],ans=0;
void insert(int u,unsigned i){
++siz[u];
if(i==s.size()){
++cnt[u];
ans+=siz[u]-cnt[u];
return;
}
int nch=s[i]-'a';
for(int j=0;j<26;j++)
if(j!=nch) f[nch][j]+=siz[ch[u][j]];
if(!ch[u][nch]) ch[u][nch]=++tot;
insert(ch[u][nch],i+1);
}
int main(){
ios::sync_with_stdio(0);cin.tie(0);
cin>>n>>q;
for(int i=1;i<=n;i++){
cin>>s;
insert(1,0);
}
while(q--){
string t;
cin>>t;
long long anst=ans;
for(int i=0;i<26;i++)
for(int j=i+1;j<26;j++)
anst+=f[t[i]-'a'][t[j]-'a'];
printf("%lld\n",anst);
}
return 0;
}
其余题解咕。