这里写自定义目录标题
【2020 ICPC Asia East Continent Final】赛前训练
A - Namomo Subsequence
输入:
输出:
样例:
解析:
“namomo”类子序列可以拆为"na"和“momo”两部分,两部分分别计算然后乘起来容斥一下即可,分5种情况:abcdcd (b!=c、a!=b、c!=d)、cbcdcd (c!=d、b!=c、c!=b), adcdcd (a!=d、c!=d、d!=c), dbcdcd (d!=b、b!=c、c!=d), ababab(a!=b) 遍历每个"m"并枚举每一个"o",结果为abcdcd-cbcdcd-adcdcd-dbcdcd+ababab,时间复杂度62*n
代码:
#include<iostream>
#include<cstring>
using namespace std;
typedef long long LL;
const int N = 1e6+5,mod=998244353;
char str[N];
int len;
int dp1[64][N];//dp1[j][i] 在i的位置时,向后str[i]jstr[i]j有多少str[i]!=j
int dp3[62];//dp3[i] 向后有多少i
int dp2[62];//dp2[i] 向前有多少i
int dp0[62];//向前ij有多少i!=j
LL ab[62][62];//ab[i][j] 向后有多少形如ij的 (i!=j)
LL bab[62][62];//bab[i][j] 向后有多少形如jij的(i!=j)
LL ans=0;
LL xb[62];// xb[i] 向前有多少形如ib的 (i!=b,b任意)
LL ax[62];// ax[i] 向前有多少形如ai的 (i!=a,a任意)
LL tt[62][62];// tt[i][j] 向前有多少形如ij的 (i!=j)
int mpp(int ch){
if(ch>='0'&&ch<='9'){
return ch-'0';
}
if(ch>='A'&&ch<='Z'){
return ch-'A'+10;
}
return ch-'a'+36;
}
int mp[256];
int main(){
scanf("%s",str+1);
len=strlen(str+1);
for(int i='0';i<='9';++i)mp[i]=mpp(i);
for(int i='A';i<='Z';++i)mp[i]=mpp(i);
for(int i='a';i<='z';++i)mp[i]=mpp(i);
for(int i=len;i>=1;--i){
int c=mp[str[i]];
for(int j=0;j<62;++j){
if(c==j)continue;
dp1[j][i]=dp1[j][i]+bab[c][j];
if(dp1[j][i]>=mod)dp1[j][i]-=mod;
bab[j][c]=(bab[j][c]+ab[j][c]);
if(bab[j][c]>=mod)bab[j][c]-=mod;
ab[c][j]=ab[c][j]+dp3[j];
if(ab[c][j]>=mod)ab[c][j]-=mod;
}
dp3[c]++;
}
for(int i=1;i<=len;++i){
int c=mp[str[i]];
LL sum=0;
for(int j=0;j<62;++j){
if(j!=c){
sum=(sum+dp0[j]);
if(sum>=mod)sum-=mod;
}
}
for(int j=0;j<62;++j){
if(c==j){
dp0[c]=((LL)dp0[c]+i-1-dp2[c]);
if(dp0[c]>=mod)dp0[c]-=mod;
ax[j]=(ax[j]+i-1-dp2[j]);
if(ax[j]>=mod)ax[j]-=mod;
continue;
}
LL temp=dp1[j][i];
LL db=(xb[j]-tt[c][j]+mod);
if(db>=mod)db-=mod;
xb[j]=(xb[j]+dp2[j]);
if(xb[j]>=mod)xb[j]-=mod;
tt[c][j]=(tt[c][j]+dp2[j]);
if(tt[c][j]>=mod)tt[c][j]-=mod;
ans=(ans+(sum-xb[c]-ax[j]-db+tt[j][c]+3LL*mod)%mod*temp)%mod;
}
dp2[c]++;
}
printf("%lld\n",ans%mod);
return 0;
}
F - Rooks
签到题,按X轴排一下序,按Y轴排一下序,判断相邻的节点即可。
L - Square
解析:
首先对每一个数质因子分解,并对每一个质因子的指数对2取模(2倍的质因子对结果无影响),对每一个质因子分开讨论,发现现规律:如果要使数组满足条件,对于这个质因子要么所有数都有,要么都没有(指的是指数对2取模为0),因为如果只有部分有,那必存在相邻的两一个有,一个没有,这中情况是不满足这两个数的乘积是完全平方数的。据此可的解
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=1e6+10,mod=1e9+7;
int a[N];
int cnt[N];
void div(int x)
{
for(int i=2;i*i<=x;i++)
{
int c=0;
while(x%i==0)
{
x/=i;
c++;
}
c%=2;
cnt[i]+=c;
}
if(x>1)cnt[x]++;
}
LL qpow(LL a,LL k,LL p)
{
LL res=1;
while(k)
{
if(k&1)res=res*a%p;
k>>=1;
a=a*a%p;
}
return res;
}
int main()
{
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
for(int i=1;i<=n;i++)
{
div(a[i]);
}
LL ans=1;
for(int i=1;i<N;i++)
{
if(cnt[i])
{
ans=ans*qpow(i,min(cnt[i],n-cnt[i]),mod)%mod;
}
}
printf("%lld",ans);
}