BZOJ4724 [POI2017]Podzielno

187 篇文章 0 订阅
79 篇文章 0 订阅

标签:数论,二分

题目

题目传送门

Description

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

Input

第一行包含两个正整数B(2<=B<=10^6),q(1<=q<=10^5)。
第二行包含B个正整数a[0],a[1],a[2],…,aB-1
接下来q行,每行一个整数k(0<=k<=10^18),表示一个询问。

Output

输出q行,每行一个整数,依次回答每个询问,如果那一位不存在,请输出-1。

Sample Input

3 3
1 1 1
0
1
2

Sample Output

0
2
-1

分析

结论题:若一个数被B-1整除,则它在B进制下各个位置的和一定能被B-1整除

证明去看这位大爷题解吧

然后删去那个余数,做一遍前缀和,二分查询答案即可

code

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<algorithm>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define dep(i,a,b) for(int i=a;i>=b;i--)
#define ll long long
#define mem(x,num) memset(x,num,sizeof x)
#define reg(x) for(int i=last[x];i;i=e[i].next)
using namespace std;
inline ll read(){
    ll f=1,x=0;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
//**********head by yjjr**********
#define mid ((l+r)>>1) 
const int maxn=1e6+6;
ll a[maxn],s=0;int B,Q;
int main()
{
    B=read(),Q=read();
    rep(i,0,B-1){
        a[i]=read();
        s=(s+a[i]*i)%(B-1);
    }
    if(s)a[s]--;
    rep(i,1,B-1)a[i]+=a[i-1];
    while(Q--){
        ll x=read()+1;
        int ans=-1,l=0,r=B-1;
        while(l<=r){
            if(a[mid]>=x)ans=mid,r=mid-1;
            else l=mid+1;
        }
        printf("%d\n",ans);
    }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值