A. Cover in Water
类似于mc中的填水规则,模拟即可。如果有长度大于2的水槽就可以无限取水,答案为2;否则计算所有水槽总长度。
#include<bits/stdc++.h>
using namespace std;
int main()
{
int t,n;
vector<int>v;
string s;
cin>>t;
while(t--)
{
v.clear();
cin>>n;
cin>>s;
s=s+'#';
for(int i=0;i<n;i++)
{
if(s[i]=='#') continue;
for(int j=i;j<=n;j++)
{
if(s[j]=='#')
{
v.push_back(j-i);
i=j;
break;
}
}
}
if(!v.size())
{
cout<<"0\n";
continue;
}
int flag=0;
for(int i=0;i<v.size();i++)
if(v[i]>2)
{
flag=1;
break;
}
if(flag) cout<<"2\n";
else
{
int sum=0;
for(int i=0;i<v.size();i++) sum+=v[i];
cout<<sum<<'\n';
}
}
}
B. Laura and Operations
猜结论,看abc中奇数多还是偶数多,多的就是1。
#include<bits/stdc++.h>
using namespace std;
int main()
{
int t,a[4],st[4];
cin>>t;
while(t--)
{
memset(st,0,sizeof(st));
int maxx=0;
for(int i=1;i<=3;i++) cin>>a[i],a[i]%=2;
if(a[1]==a[2]&&a[2]==a[3]) cout<<"1 1 1\n";
else
{
int x=0,y=0;
for(int i=1;i<=3;i++)
if(a[i]==1) x++;
else y++;
if(x<y)
for(int i=1;i<=3;i++)
if(a[i]) cout<<"1 ";
else cout<<"0 ";
else
for(int i=1;i<=3;i++)
if(a[i]==0) cout<<"1 ";
else cout<<"0 ";
cout<<'\n';
}
}
}
C. Anji's Binary Tree
模拟树形dp即可,根据叶子结点和父结点的关系判断是否对dp值+1,注意只有叶子节点才能为U,不然会走死循环。
#include<bits/stdc++.h>
using namespace std;
int t,n,l[300010],r[300010],dp[300010],dpl[300010],dpr[300010];
string s;
void dfs(int u)
{
if(l[u])
{
dfs(l[u]);
if(s[u]=='L') dpl[u]=dp[l[u]];
else dpl[u]=dp[l[u]]+1;
}
if(r[u])
{
dfs(r[u]);
if(s[u]=='R') dpr[u]=dp[r[u]];
else dpr[u]=dp[r[u]]+1;
}
if(l[u]&&!r[u]) dp[u]=dpl[u];
else if(!l[u]&&r[u]) dp[u]=dpr[u];
else if(l[u]&&r[u]) dp[u]=min(dpl[u],dpr[u]);
else dp[u]=0;
}
void solve()
{
cin>>n;
for(int i=1;i<=n;i++) dp[i]=0,dpl[i]=0,dpr[i]=0;
cin>>s;
s='?'+s;
for(int i=1;i<=n;i++) cin>>l[i]>>r[i];
dfs(1);
cout<<dp[1]<<'\n';
}
int main()
{
cin>>t;
while(t--) solve();
}
D. Small GCD
注意到只需要对更小的两个数求gcd,考虑将数组排序后固定最大值,那么从左向右做扫描依次对每个最大值做计算,然后从最大值的左侧寻找两个较小的值求gcd总和。问题就变为如何求区间中任意两数的gcd总和,和hdu4676类似,答案为,d为所有数的因子。
本题只需要求n-1个区间的答案,且区间的左端点均为1,那么就比较好维护了。每次加入新的数时,如果某个因子d的次数增加1,那么由组合数可知,答案就会增加,然后令加1即可,时间复杂度为
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=100010;
ll res=0,sum=0;
int t,n,primes[N],Cnt;
ll phi[N],a[N],cnt[N];
bool st[N];
void init(int n)
{
phi[1]=1;
for(int i=2;i<=n;i++)
{
if(!st[i])
{
primes[Cnt++]=i;
phi[i]=i-1;
}
for(int j=0;i*primes[j]<=n;j++)
{
st[i*primes[j]]=true;
if(i%primes[j]==0)
{
phi[i*primes[j]]=phi[i]*primes[j];
break;
}
phi[i*primes[j]]=phi[i]*(primes[j]-1);
}
}
}
void add(int x)
{
for(int i=1;i<=x/i;i++)
{
if(x%i==0)
{
sum+=phi[i]*cnt[i],cnt[i]++;
if(i!=x/i) sum+=phi[x/i]*cnt[x/i],cnt[x/i]++;
}
}
}
void solve()
{
memset(cnt,0,sizeof(cnt));
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
sort(a+1,a+n+1);
sum=0,res=0;
for(int i=1;i<n;i++) add(a[i]),res+=sum;
cout<<res<<'\n';
}
int main()
{
cin>>t;
init(100000);
while(t--) solve();
}