Educational Codeforces Round 157 (Rated for Div. 2) 复盘
又是vp的稀烂的一场。
A没问题。被B一道800卡了。
但是确实非常简单,就是从式子上入手,让\(|x_1-x_2|+|y_1-y_2|\)最小就可以了。
所以就把两维度分开来看,这两维之间的距离是不会影响代价的,这是曼哈顿距离的特点。
那么就很明显了,就是从中间分开。
但是我vp的时候并没有看出来。而是在猜结论。因为我不知道怎么想,但是事实上我就应该直接分析我的答案是什么样的,然后得出结论。我没有去思考,这非常不好。这题我感觉就是这样的。我其实可以适当的跳过一些证明,猜一些小结论。比如这题,我开始的时候就被分成两组这个东西给拉扯住了,没有往下想的思路了。很要命,但是事实上这个根本就不是什么很难的东西。以后看题可以跟注重从结果出发来分析题目。
然后就是C,更是依托。赛时写了160行。只能说我的代码能力是更强了,这种事都干得出来。。。
然而cf的c题根本就不会让你写这么多。我其实就没有仔细分析题目就去写了。
我应该去思考一下,另一半到底应该满足写什么条件,然后在根据这条件去维护一些东西。
很明显,满足的条件就是1.长度 2.数值和。如果我知道了另一半所需要用的长度,那么,那一边的数值和也就知道了。
那这不就很好维护吗?直接用一个数组就可以了。然后我就把5个情况全部分开。。写傻了。。然后还wa了,都不知道错哪里了。
好了,现在知道了。160行写错了一行,就死了。
服了,但凡做法简单点。
#include<bits/stdc++.h>
#define ll long long
using namespace std;
inline ll read() {
char c=getchar();ll a=0,b=1;
for(;c<'0'||c>'9';c=getchar())if(c=='-')b=-1;
for(;c>='0'&&c<='9';c=getchar())a=a*10+c-48;return a*b;
}
ll n;
string s[200001];
ll f[351][351];
ll count(string a,ll x)
{
ll ans=0;
for(ll i=0;i<x;i++)ans+=a[i]-'0';
return ans;
}
int main()
{
// freopen("1.in","r",stdin);
// freopen("2.out","w",stdout);
// ll T=read();
// while(T--)
{
n=read();
for(ll i=1;i<=n;i++)
{
cin>>s[i];
// cout<<count(s[i],s[i].size())<<endl;
}
memset(f,0,sizeof(f));
ll ans=0;
for(ll i=1;i<=n;i++)
{
if(s[i].size()==2)
{
f[count(s[i],2)][0]++;
}
else
if(s[i].size()==4)
{
if(count(s[i],4)-count(s[i],1)>0)
f[count(s[i],1)][count(s[i],4)-count(s[i],1)]++;
f[0][count(s[i],4)]++;
}
}
for(ll i=1;i<=n;i++)
{
if(s[i].size()==2)
{
ans+=f[count(s[i],2)][0];
for(ll j=1;j<=9;j++)
{
ans+=f[j][count(s[i],2)+j];
}
}
if(s[i].size()==4)
{
ll forth=count(s[i],4)-count(s[i],3);
if(count(s[i],3)-forth>0)ans+=f[count(s[i],3)-forth][0];//2
ans+=f[0][count(s[i],4)];
}
}
memset(f,0,sizeof(f));
for(ll i=1;i<=n;i++)//1
{
if(s[i].size()==1)
{
f[count(s[i],1)][0]++;
}
if(s[i].size()==3)
{
if(count(s[i],3)-count(s[i],1)>0)f[count(s[i],1)][count(s[i],3)-count(s[i],1)]++;
}
if(s[i].size()==5)
{
if(count(s[i],5)-count(s[i],2)>0)f[count(s[i],2)+50][count(s[i],5)-count(s[i],2)]++;
}
}
for(ll i=1;i<=n;i++)
{
if(s[i].size()==1)
{
ans+=f[count(s[i],1)][0];
for(ll k=1;k<=9;k++)
{
ans+=f[k][k+count(s[i],1)];
}
for(ll j=2;j<=18;j++)
{
ans+=f[j+50][j+count(s[i],1)];
}
}
}
// cout<<ans<<endl;
memset(f,0,sizeof(f));
for(ll i=1;i<=n;i++)//3
{
if(s[i].size()==1)
{
f[count(s[i],1)][0]++;
}
if(s[i].size()==3)
{
f[0][count(s[i],3)]++;
}
if(s[i].size()==5)
{
if(count(s[i],5)-count(s[i],1)>0)
f[count(s[i],1)][count(s[i],5)-count(s[i],1)]++;
}
}
for(ll i=1;i<=n;i++)
{
if(s[i].size()==3)
{
ll last1=count(s[i],3)-count(s[i],2);
ans+=f[0][count(s[i],3)];// 3
// cout<<ans<<endl;
if(count(s[i],2)-last1>0)
ans+=f[count(s[i],2)-last1][0];// 1
// cout<<ans<<endl;
for(ll j=1;j<=9;j++)
{
ans+=f[j][count(s[i],3)+j];// 5
}
// cout<<ans<<endl;
}
}
// cout<<ans<<endl;
memset(f,0,sizeof(f));
for(ll i=1;i<=n;i++)//5
{
if(s[i].size()==1)
{
f[count(s[i],1)][1]++;
}
if(s[i].size()==3)
{
f[count(s[i],3)][3]++;
}
if(s[i].size()==5)
{
f[count(s[i],5)][5]++;
}
}
for(ll i=1;i<=n;i++)
{
if(s[i].size()==5)
{
ll last2=count(s[i],5)-count(s[i],3);
if(count(s[i],3)-last2>0)ans+=f[count(s[i],3)-last2][1];
ll last1=count(s[i],5)-count(s[i],4);
if(count(s[i],4)-last1>0)ans+=f[count(s[i],4)-last1][3];
ans+=f[count(s[i],5)][5];
}
}
cout<<ans<<endl;
}
return 0;
}
/*
2
2 942
*/