卧薪尝胆,厚积薄发。
POI2017 Podzielno
Date: Wed Sep 05 23:06:35 CST 2018 In Category: NoCategory

Description:

$B$ 进制数,每个数字 $i$ 有 $a[i]$ 个。用这些数字组成一个最大的 $B$ 进制数 $X$ (不能有前导零,不需要用完所有数字),使得 $X$ 是 $B-1$ 的倍数。 $q$ 次询问,每次询问 $X$ 在 $B$ 进制下的第 $k$ 位数字是什么。
$1\le b \le 10^6,1\le a[i]\le 10^6$

Solution:

首先可以证明 $a^k\equiv1(mod\ a-1)$ ,只要不停减去 $(a-1)\times a^{k-1}$ ,就能削成 $1$ ,而原数是 $\begin{align}\sum_{i=0}^na[i]\times B^i=\sum_{i=0}^na[i]\end{align}$ ,所以计算一下右边的式子对 $B-1$ 取模,如果结果不为 $0$ ,删掉对应的数字,因为不存在不删除数字的方案,而只有这一种只删除一个数字的方案,所以这样 $R$ 最大,然后询问只要在前缀和数组上 $lower\_bound$ 即可。

Code:


#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
int r,q;
#define MAXR 1000010
typedef long long ll;
ll a[MAXR];
ll s[MAXR];
inline ll read()
{
register ll res = 0;
register char c = getchar();
while(!isdigit(c))c = getchar();
while(isdigit(c))
{
res = (res << 1) + (res << 3) + c - '0';
c = getchar();
}
return res;
}
int main()
{
scanf("%d%d",&r,&q);
for(register int i = 0;i < r;++i)a[i] = read();
ll sum = 0;
for(register int i = 0;i < r;++i)
sum = sum + a[i] * i;
sum = sum % ((ll)r - 1ll);
if(sum != 0)--a[sum];
s[0] = a[0];
for(register int i = 1;i < r;++i)
s[i] = s[i - 1] + a[i];
s[r] = 0x3f3f3f3f3f3f3f3f;
register ll k;
for(register int i = 1;i <= q;++i)
{
k = read();++k;
int ans = lower_bound(s + 0,s + r + 1,k) - s;
if(ans == r)puts("-1");
else printf("%d\n",ans);
}
return 0;
}
Copyright © 2020 wjh15101051
ღゝ◡╹)ノ♡