codechef It Is Axis Time

来源:互联网 发布:算命的为何准 知乎 编辑:程序博客网 时间:2024/06/14 08:32

Problem Description

Its axis time and the event managers are busy conducting meetings or their events. Each event manager is seating on a vertex of a table having shape of a regular polygon.

The table has n vertices where n is the number of event managers in the meeting.

Your task is to count the number of isosceles triangles formed such that each vertex of the triangle is a vertex of the table and all managers seating on these 3 vertices are of same gender.

Input

The first line contains an integer T. T testcases follow.
For each test case, there is only one line, which consists of a 01-string with length >= 2. 


Number of vertices n of the regular
polygon equals length of the string.


The string represents gender of managers seating on the vertices in clockwise order. 0 represents girls and 1 represents boys.

Output

For each test case, output one line in the format Case #t: ans, where t is the case number (starting from 1), and ans is the answer.

题目大意:

给你一个正n边形,告诉你它每个顶点上的数值(0或1)。要求找出三个顶点数值相同的等腰三角形。

Constraints

Sum of all n in the input <= 10^6

 

Example

Input:5010001100011110101101010Output:Case 1: 0Case 2: 1Case 3: 1Case 4: 2Case 5: 3

 

Explanation

In case 5, indices of vertices of the three monochromatic isosceles triangles are (0,3,5), (1,3,5) and (2,4,6) (assuming indices
start from 0)


题解

这题到底该算好还是不好呢?通过画图比较的结论题,跟容斥原理有点关系……委屈鄙人蒟蒻,仅把小人所理解的写在下面。

我的第一想法是将字符串“折叠”比较,hash每个状态,重复的不记,这种做法看着都会T……

这数据范围……而且nlogn的算法(我所知道的)好像跟没什么关系嘛……O(n)的更没有了吧……所以我向已A代码屈服了。

画图可知,不管n的奇偶性,正多边形总共有n*((n-1)/2)个等腰三角形,当然这些可能包含了等边的。易证:当n%3==0时,有n个等边三角形,每个共计数3次,所以此时要减去(n/3*2)。(这应该是容斥吧!)

接下来要删掉顶点不相同的三角形,分两种情况考虑:

1、当n为奇数时,设0顶点数位s0,1顶点数为s1。画图可知,任意两点可成为3个等腰三角形的边(不足三个的可视为三个等边三角形重合)。所以,一定要删去s0*s1*3个,若n%3==0,要再特判一些答案。话说特判为什么像我这样写,应该是这样的:一个三角形一定至少有两个点数字一样(抽屉原理)。因为一对不一样的点使一个等边三角形被多算两次,所以像我那样写可以。

2、当n为偶数时,设在偶数编号上的0顶点数位s00,在偶数编号上的1顶点数为s01,在奇数编号上的0顶点数位s10,数编号上的1顶点数为s11. 两个点的编号的奇偶性对这一线段所能做出的贡献是有影响的(画图可知)。所以,分类处理要删去的点,特判处理两点刚好在最长对角线上(即两点正对,因为是偶数个点,这两点所组成的线段无法构成等腰三角形)。之后对于n%3==0的情况,像1一样处理即可。

剩下的细节看代码吧!

#include<cstdio>#include<cstring>#include<cstdlib>#include<iostream>#include<cmath>#include<algorithm>#define ll long longusing namespace std;int T,n;char a[1000005];ll calcu(){ll ans=0;ans=(ll) n*((n-1)/2);if(n%3==0) ans-=n/3*2;return ans;}ll del(){ll ans;if(n%2==1)   {int s1=0,i,s0=0;    for(i=0;i<n;i++)       {if(a[i]=='0') s0++;    else s1++;   }ans=(ll)s1*s0*3;if(n%3==0)   {s1=n/3; s0=n/3*2;for(i=0;i<n;i++)       {if(a[i]!=a[(i+s1)%n]) ans--;    if(a[i]!=a[(i+s0)%n]) ans--;   }   }return ans/2;   }else   {int i,s00=0,s01=0,s10=0,s11=0;for(i=0;i<n;i+=2)   {if(a[i]=='0') s00++;    else s01++;   }for(i=1;i<n;i+=2)   {if(a[i]=='0') s10++;    else s11++;   }ans=(ll)s00*s11*2; ans+=(ll)s01*s10*2;ans+=(ll)s00*s01*4; ans+=(ll)s10*s11*4;int n1,n2;n1=n/2;for(i=0;i<n;i++)   {if(a[i]!=a[(i+n1)%n]) ans--;}if(n%3==0)   {int s1=n/3,s0=n/3*2;for(i=0;i<n;i++)       {if(a[i]!=a[(i+s1)%n]) ans--;    if(a[i]!=a[(i+s0)%n]) ans--;   }   }return ans/2;   }}int main(){scanf("%d",&T);int k;for(k=1;k<=T;k++)   {scanf("%s",a); n=strlen(a);printf("Case %d: %lld\n",k,calcu()-del());   }return 0;}

0 0
原创粉丝点击