重建
A国拥有N个城市编号为0~N-1,这N个城市由N条双向道路所连接形成了一个环。环上城市的编号沿顺时针方向递增(除第N-1号城市外)。
不幸的是,A国遭遇了一场地震,摧毁了所有N个城市的电力系统。在地震后的K天中,第i天会由城市Ci派出一支重建队伍,他们从第Ci个城市出发,找到顺时针方向上第一个电力系统未被修复的城市并修复它。在该城市电力系统被修复后,所有与它有联系的城市将会向它提供1吨援助物资。城市A与城市B有联系仅当A与B是同一个城市,或者城市A可以沿着道路在只经过电力系统被修复的城市的情况下到达城市B。
请你编写一个程序帮助A国统计在K天的重建过程中的援助物资总量。
输入
一行三个整数N,K,C1
C2到Ck由以下公式计算
Ci=(Ci-1+6655)×1551 % N
输出
输出一个整数,表示重建过程中的援助物资总量
样例输入
6 4 0
样例输出
6数据规模
对于40%的数据,1≤K<N≤1,000
对于100%的数据,1≤K<N≤3,000,000
时限2s,空间265MB
经过分析,我们可以知道。这道题目的大概意思是:
有N个城市,其中编号分别为0~N-1,各城市与相邻数字相连,形成环。其中编号0城市与编号1相连外,还与编号N-1城市相通。
其次,题目中我们可以发现,每天都有并且只有一个重建队伍在运作,他们在第i天被Ci城市派出,以他们出发的城市开始,顺时针也就是从大到小顺序进行城市重建,他们在该天内只重建1个城市。
同时,题目要求求的援救物资总量,来源于两部分。
一部分是该城市本身为自己提供了1的救援物资,另一部分是附近城市,即指只经过已重建的城市的已重建的城市提供给该城市1的救援物资。
所以,我们计算当天,该城市所得即为1(该城市为自己提供的救援物资)+该城市逆时针开始连续的已完成重建的城市数+该城市逆时针开始连续的已完成重建的城市数。
换句话说,就是该城市包括它自己的连成一片的已完成重建的城市数。
所以,我们可以选择建两个数组,一个表示该城市顺时针到达的第一个未重建的城市next,一个表示该城市逆时针到达的第一个未完成重建的城市before。
那么我们就可以知道,当一个城市完成重建时,那么就会有 (next-before-1)的救援物资发出,为了保证该数据必定大于0,我们可以选择(next-before-1+n)%n 来处理。
代码如下
#include <cstdio>
using namespace std;
long long before[3000000],next[3000000];
long long n,k,now,c,d,ans;
bool bo[3000000];
long long int getfather(int );
long long int getson(int );
inline long long int read()
{
int x=0;
char c=getchar();
while ((c<'0')||(c>'9'))
c=getchar();
while ((c>='0')&&(c<='9'))
{
x=(x<<3)+(x<<1)+c-'0';
c=getchar();
}
return x;
}
int main()
{
n=read();
k=read();
c=read();
for (int i=0;i<n;i++)
{
before[i]=i-1;
next[i]=i+1;
}
next[n-1]=0;
before[0]=n-1;
bo[c]=true;
ans++;
now++;
while (++now<=k)
{
c=(c+6655)*1551%n;
if (bo[c])
d=getfather(c);
else
d=c;
bo[d]=true;
ans+=(getfather(d)-getson(d)-1+n)%n;
}
printf("%lld",ans);
return 0;
}
long long int getson(int a)
{
if (bo[before[a]])
before[a]=getson(before[a]);
return before[a];
}
long long int getfather(int a)
{
if (bo[next[a]])
next[a]=getfather(next[a]);
return next[a];
}