[CF819D]Mister B and Astronomers
Posted ZLTJohn
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[CF819D]Mister B and Astronomers相关的知识,希望对你有一定的参考价值。
有n个wzd在仰望星空,第一个wzd会在第0秒仰望星空,第i个wzd会在i-1个仰望完之后的a[i]秒后仰望星空一秒。第n个仰望完后第一个接着,一直循环下去。
有一颗星星在一闪一闪,他有一个参数T,含义是每T秒闪一次,但不知道它从0~T-1秒的哪一个时候会闪。
定义一个wzd的“幸运值”为满足以下条件的x的个数:
x∈[0,T−1]
x
∈
[
0
,
T
−
1
]
,星星从第x秒开始闪时,这个wzd是第一个看到的人。
问每个wzd的幸运值
T<=1e9,n<=2e5
解题思路
定义
y[i]=∑i=2..ia[i],S=∑i=1..na[i]
y
[
i
]
=
∑
i
=
2..
i
a
[
i
]
,
S
=
∑
i
=
1..
n
a
[
i
]
那么第i个wzd仰望星空的时间就是
x∗S+y[i]
x
∗
S
+
y
[
i
]
。
对于一个闪烁开始时刻t,如果有两个wzd都看到了这颗星星,一定是x小的,或者x相同时y小的那个wzd最先看到。
那么我们换个角度考虑这个问题。首先,对于
i<j,如果y[i]≡y[j](mod T)
i
<
j
,
如
果
y
[
i
]
≡
y
[
j
]
(
m
o
d
T
)
,那么j的幸运值为0,因为i无论什么时候都会比j先看到。那么对于一个i而言,他的幸运值如果为x,那么一定存在一个k满足
y[i]+x∗S≡y[k]
y
[
i
]
+
x
∗
S
≡
y
[
k
]
,可以想象成y[i]在数轴上一次跳S格,然后跳x次会跳到y[k]去,期间每到一个地方,就占用掉这个值,我们想知道每个i会占用多少个值。
我们知道对于S和T,跳来跳去在模意义下会形成gcd(S,T)个环,所以我们把i按y[i]%gcd(S,T)分组,假设模出来的数是z,那么他分到第z组。
对于一个组z,我们从
[0,T−1]的z
[
0
,
T
−
1
]
的
z
开始跳,确定每个元素i在第几次跳的时候被碰到,记为X[i],然后升序排序,每个wzd的幸运值就是X[i+1]-X[i]了。
实现可以用set+map乱搞。
代码
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
//开 O2!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
using namespace std;
#define fo(i,j,k) for(i=j;i<=k;i++)
#define fd(i,j,k) for(i=j;i>=k;i--)
#define cmax(a,b) (a=(a>b)?a:b)
#define cmin(a,b) (a=(a<b)?a:b)
typedef long long ll;
typedef long long LL;
typedef double db;
const int N=2e5+5,M=1e3+5,mo=1e9+7;
map<int,int> mp,czy;
multiset<int> tr[N];
multiset<int> :: iterator it;
int pp[N],a[N],n,T,A,B,S,d,rem,ka,ts,prt[N],x[N],y[N],i;
int exgcd(int a,int b,int &x,int &y)
if (!b)
x=1;
y=0;
return a;
int ret=exgcd(b,a%b,y,x);
y-=a/b*x;
return ret;
int main()
freopen("d.in","r",stdin);
//freopen("d.out","w",stdout);
scanf("%d %d",&T,&n);
fo(i,1,n)
scanf("%d",a+i);
if (i!=1) y[i]=(y[i-1]+a[i])%T;
if (!mp[y[i]]) mp[y[i]]=i,pp[i]=1;
S=(S+a[i])%T;
d=exgcd(S,T,A,B);
S/=d;
T/=d;
A%=T;
if (A<0) A+=T;
fo(i,1,n)
if (pp[i])
ka=y[i]%d;
if (!czy[ka]) czy[ka]=++ts;
rem=y[i]-ka;
ka=czy[ka];
// aS+bT=rem
rem/=d;
x[i]=1ll*A*rem%T;
tr[ka].insert(x[i]);
fo(i,1,n)
if (pp[i])
ka=czy[y[i]%d];
it=tr[ka].find(x[i]);
it++;
prt[i]=-x[i];
if (it==tr[ka].end())
prt[i]+=T;
it=tr[ka].begin();
prt[i]+=*it;
fo(i,1,n) printf("%d ",prt[i]);
以上是关于[CF819D]Mister B and Astronomers的主要内容,如果未能解决你的问题,请参考以下文章
CF819DMister B and Astronomers EXGCD
#421(div2)B. Mister B and Angle in Polygon
codeforces 819B - Mister B and PR Shifts(思维)
#420(div2)C. Mister B and Boring Game
Codeforces Round #421 (Div. 2)B Mister B and Angle in Polygon