A
题意:
连续数字和为0的序列个数
题解:
直接用map的前缀和计数就行,不用忘记开longlong
代码:
#include <cstdio>
#include <map>
#define LL long long
using namespace std;
const int N=200005;
int n,a[N];map<LL,LL>mp;
int main()
{
scanf("%d",&n);
mp[0]=1;LL sum=0,ans=0;
for (int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
sum+=(LL)a[i];ans+=mp[sum];
mp[sum]++;
}
printf("%lld",ans);
}
B
题意:
A表示向下平移,B表示向右平移,剩下的看样例解释吧
题解:
我枚举的A,然后把矩阵copy一份,计算出行和列的hash值,这样再枚举B的话就可以直接判断了
check是O(n)的,只需要判断第i行的hash值和第i列的hash值都相等就可以了
然后枚举B都是O(n)的转移,把每一行的hash值平移,即abc变成cab,这个转移是O(1)的,每一行都往后平移,那么是O(n)的
列的话整列是不变的,只需要平移就好
总时间复杂度O(n^3)
代码:
#include <cstdio>
#define LL long long
using namespace std;
const int mod=19260817;
const int base=31;
const int N=305;
char a[N][N],st[N],copy[N][N];
int hashA[N],hashB[N],hashC[N];
LL ksm(LL a,LL k)
{
LL ans=1;
for (;k;k>>=1,a=a*a%mod)
if (k&1) ans=ans*a%mod;
return ans;
}
int main()
{
int n;scanf("%d",&n);int ans=0;
for (int i=1;i<=n;i++)
{
scanf("%s",st+1);
for (int j=1;j<=n;j++) a[i][j]=st[j];
}
LL inv=ksm(base,mod-2);
LL what=ksm(base,n-1);
for (int A=0;A<n;A++)
{
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++)
copy[(i+A-1+n)%n+1][j]=a[i][j],hashA[i]=0,hashB[i]=0;
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++)
{
hashB[i]=(hashB[i]*base%mod+copy[j][i])%mod;
hashA[i]=(hashA[i]*base%mod+copy[i][j])%mod;
}
for (int B=1;B<=n;B++)
{
bool fff=1;
for (int i=1;i<=n;i++)
if (hashA[i]!=hashB[i]) {fff=0;break;}
if (fff) ans++;
for (int i=1;i<=n;i++)
hashA[i]=((hashA[i]-copy[i][n-B+1]+mod)*inv%mod+copy[i][n-B+1]*what%mod)%mod;
int t=hashB[n];
for (int i=n;i>=2;i--)
hashB[i]=hashB[i-1];
hashB[1]=t;
}
}
printf("%d",ans);
}