题目链接:
http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=4054
题意就是一个小孩走一段路,这条路上有n个红绿灯,并且告诉了你初始红绿灯的状态,用1表示路灯,0表示红灯,并且没经过一秒红绿灯就转换,从绿灯变为红灯或是从红灯变为绿灯。小孩走这一段路,如果碰到了绿灯直接走过去,如果碰到了红灯停一秒钟等红灯变为绿灯在走过去,定义t(p,q)为从p点走到q点所需要的时间,q>p,并且q和p可以取任何值,问t(p,q)的总和是多少。
直接画图找规律,可以发现,如果是红灯的话,sum=sum-2-2*(thenum-1);第一个是绿灯第二个是红灯的话,是sum=sum-1;第一个是绿灯,第二个是绿灯的话,是sum=sum-1-2*(thenum-1); 其中sum是从第i个点出发,走到i+1,i+2.。。。i+n的和。thenum是还剩下几个点。
详情见代码:
#include <iostream>
#include <cstring>
#include <stdio.h>
using namespace std;
const int inf=1e5+7;
int arr[2][inf];
typedef long long ll;
int main()
{
int T;
scanf("%d",&T);
string str;
while(T--)
{
cin>>str;
for(int i=0;i<str.length();i++)
{
arr[0][i]=str[i]-48;
arr[1][i]=1-arr[0][i]; //其中技巧使用。
}
int len=str.length();
ll sum1=0,sum=0; //这里的sum是零。
int k=0;
for(int i=0;i<len;i++)
{
if(arr[k][i]==0) //即使是过去之后任然是不变的。
{
sum1=sum1+2; //只求算出一层的来。
sum+=sum1;
}
else
{
sum1=sum1+1;
sum+=sum1;
k=(k+1)%2;
}
}
sum1=0;
ll temp=0;
ll ans=sum;
int thenum=str.length();
k=0;
for(int i=0;i<len-1;i++) //到3,和4正好对应。
{
if(arr[k][i]==0)
{
sum=sum-2-2*(thenum-1);
thenum--;
ans+=sum;
}
else if(arr[k][i]==1&&arr[k][i+1]==0) //说明是一。不论是哪一个都是要加一的。
{
sum=sum-1;
thenum--;
ans+=sum;
}
else
{
sum=sum-1-2*(thenum-1);
thenum--;
ans+=sum;
}
}
cout<<ans<<endl;
}
return 0;
}