因为我太弱,所以只做了Div.2。
T1:
就这还要题解?
暴力枚举,慢走。
T2:
假设腰长为\(b\),底边长为\(c\)。
显然\(b+c>b\)恒成立。
所以只要\(b+b>c\)即可。
故\(0 < c < 2b\)。
用桶来统计一遍,再在桶上套一个前缀和。
令\(i\)出现了\(buc_i\)次,前缀和为\(sum_i\)
对于腰长为\(b\)的情况,分两种:
一、非等边:在当前长度为\(b\)的棍子中选两个,再在不为\(b\)且\(< 2b\)的里面选\(1\)个。
有\(\binom{buc_i}{2} \left ( sum_{2i-1}-buc_i \right )\)种情况。
二、等边:在长度为\(b\)的棍子中选三个。
有\(\binom{buc_i}{3}\)种情况。
枚举\(b\),两种情况加起来,再模\(998244353\)。
code:
#include<bits/stdc++.h>
using namespace std;
const int mod=998244353;
int a[200005];int buc[200005];int sum[200005];
int main()
{
int n;cin>>n;
for(int i=1;i<=n;++i)
{
cin>>a[i];++buc[a[i]];
}
for(register int i=1;i<=200000;++i)
{
sum[i]=sum[i-1]+buc[i];
}
long long ans=0;
for(register int i=1;i<=200000;++i)
{
if(buc[i]>1)
{
long long bdb=1ll*buc[i]*(buc[i]-1)/2%mod*(sum[min(((i<<1)-1),200000)]-buc[i]);
long db=1ll*buc[i]*(buc[i]-1)*(buc[i]-2)/6%mod;
(ans+=(bdb+db)%mod)%=mod;
}
}
cout<<ans%mod<<endl;
return 0;
}
T3:
需要稍微思考一下。
看到唯一的操作,先转一个\(2 \times 2\)的区域。
容易发现:同一列的数字永远在一起。
然后,一列的书每移动一下,就会上下颠倒。
容易发现:一列数字,移动奇数次则上下颠倒,否则不变。
所以就很好判定有无解了。
那怎样判定移动次数呢?
我们可以把一列看成一个数。
坑待填。