Cod sursa(job #467366)

Utilizator cosmin79Carabet Cosmin Andrei cosmin79 Data 28 iunie 2010 15:15:11
Problema PScPld Scor 0
Compilator cpp Status done
Runda Arhiva de probleme Marime 1.97 kb
#include <stdio.h>
#define NMAX 1000005
#define MOD 9901
#define LMAX 2000005
#define ll long long
char A[NMAX],D[LMAX],spec[LMAX];
int n,B[LMAX],C[LMAX],exp[LMAX],VAL,r,nr[LMAX];
ll rez;
inline int lit(char x)
{
	return x>='a' && x<='z';
}
void read()
{
	fgets(A+1,NMAX,stdin);
	while (lit(A[n+1])) n++;
	int i;
	for (i=1; i<n; i++)
	{
		D[++r]=A[i];
		D[++r]='a';
		spec[r]=1;
	}
	D[++r]=A[i];
	n=r;
}
int euler(int n)
{
	int i=1,rez=n; 
	for (i=2; i*i<=n; i++)
	{
		if (n%i==0)
		{
			while(n%i==0)
				n/=i;
			rez=rez/i*(i-1);
		}
	}
	if (n!=1)
		rez=rez/n*(n-1);
	return rez;
}
void precompute()
{
	int i,act=1;
	exp[0]=1;
	VAL=euler(MOD)-1;
	for (i=1; i<=n; i++)
	{
		B[i]=B[i-1]+act*(D[i]-'a');
		nr[i]=nr[i-1];
		if (spec[i])
			nr[i]++;
		if (B[i]>=MOD)
			B[i]%=MOD;
		act*=26;
		if (act>=MOD)
			act%=MOD;
		exp[i]=act;
	}
	act=1;
	for (i=n; i>=1; i--)
	{
		C[i]=C[i+1]+act*(D[i]-'a');
		if (C[i]>=MOD)
			C[i]%=MOD;
		act*=26;
		if (act>=MOD)
			act%=MOD;
	}
}
int lgput(int baza,int exp)
{
	int part=1,part2=baza;
	while (exp)
	{
		if (exp & 1)
			part*=part2,part%=MOD;
		part2*=part2;
		part2%=MOD;
		exp>>=1;
	}
	return part;
}
inline int ok(int poz,int st,int dr)
{
	int p1=B[poz]-B[st-1];
	if (p1<0)
		p1+=MOD;
	int val1=p1*lgput(exp[st-1],VAL);
	if (val1>=MOD)
		val1%=MOD;
	int p2=C[poz]-C[dr+1];
	if (p2<0)
		p2+=MOD;
	int val2=p2*lgput(exp[n-dr],VAL); 
	if (val2>=MOD)
		val2%=MOD;
	if (val1==val2)
		return 1;
	return 0;
}
int cbin(int poz)
{
	int i,step;
	for (step=1; step<=poz; step<<=1);
	for (i=poz; step; step>>=1)
		if (i-step>0 && poz+(poz-i+step)<=n && ok(poz,i-step,poz+(poz-i+step)))
			i-=step;
	return i;
}
void solve()
{
	int i,poz;
	precompute();
	for (i=1; i<=n; i++)
	{
		poz=cbin(i);
		rez+=(i-poz+1)-(nr[i]-nr[poz-1]);
	}
}
int main()
{
	freopen("pscpld.in","r",stdin);
	freopen("pscpld.out","w",stdout);
	read();
	solve();
	printf("%lld\n",rez);
	return 0;
}