Podzielno

Posted kissheart

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Podzielno相关的知识,希望对你有一定的参考价值。

问题 B: Podzielno

时间限制: 1 Sec  内存限制: 128 MB
提交: 97  解决: 31
[提交] [状态] [讨论版] [命题人:admin]

题目描述

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

 

输入

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

 

输出

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

 

样例输入

3 3
1 1 1
0
1
2

样例输出

0
2
-1

 

问题

  中文题意 不做解释

分析

  有一个结论,就是一个数能被B-1整除当且仅当这个数在B进制下的每一位的和能被B-1整除。
  

  证明:
  当一个数的某一位+1时,若进位,则这一位要减去B-1,下一位要+1,则总的贡献是+1.
  当一个数的某一位-1时,若退位,则这一位要加上B-1,下一位要-1,则总的贡献是-1.
  于是当一个数加上B-1时,它在B进制下每一位的总和对B-1取模的值是不变的。
  要是B-1的倍数,那么各位之和对B-1取余一定是零。

    a*Bk≡a (mod (B-1) )
   

  因为要求最大的B进制数,所以贪心每个数都占一位,对B-1取余,减去一个余数。

  所以求一个前缀和,lower_bound求值就可以了。

  

技术分享图片
///  author:Kissheart  ///
#include<stdio.h>
#include<algorithm>
#include<iostream>
#include<string.h>
#include<vector>
#include<stdlib.h>
#include<math.h>
#include<queue>
#include<deque>
#include<ctype.h>
#include<map>
#include<set>
#include<stack>
#include<string>
#define INF 0x3f3f3f3f
#define FAST_IO ios::sync_with_stdio(false)
const double PI = acos(-1.0);
const double eps = 1e-6;
const int MAX=1e6+10;
const int mod=1e9+7;
typedef long long ll;
using namespace std;
#define gcd(a,b) __gcd(a,b)
inline ll lcm(ll a,ll b){return a/gcd(a,b)*b;}
inline ll qpow(ll a,ll b){ll r=1,t=a; while(b){if(b&1)r=(r*t)%mod;b>>=1;t=(t*t)%mod;}return r;}
inline ll inv1(ll b){return qpow(b,mod-2);}
inline ll exgcd(ll a,ll b,ll &x,ll &y){if(!b){x=1;y=0;return a;}ll r=exgcd(b,a%b,y,x);y-=(a/b)*x;return r;}
inline ll read(){ll x=0,f=1;char c=getchar();for(;!isdigit(c);c=getchar()) if(c==-) f=-1;for(;isdigit(c);c=getchar()) x=x*10+c-0;return x*f;}
//freopen( "in.txt" , "r" , stdin );
//freopen( "data.txt" , "w" , stdout );
ll B,k,q;
ll a[MAX],sum[MAX];
ll s,p;
int main()
{
    scanf("%lld%lld",&B,&q);
    p=B-1;
    for(ll i=0;i<B;i++)
    {
        scanf("%lld",&a[i]);
        s=(s+i*a[i])%p;
    }
    if(s) a[s]--;
    sum[0]=a[0];
    for(ll i=1;i<B;i++) sum[i]=sum[i-1]+a[i];
    while(q--)
    {
        scanf("%lld",&k);
        if(k+1>sum[B-1])
            printf("-1
");
        else
        {
            ll pos;
            pos=lower_bound(sum,sum+B,k+1)-sum;
            printf("%lld
",pos);
        }
    }
    return 0;
}
View Code

 

以上是关于Podzielno的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ4724[POI2017]Podzielno 数学+二分

微信小程序代码片段

VSCode自定义代码片段——CSS选择器

谷歌浏览器调试jsp 引入代码片段,如何调试代码片段中的js

片段和活动之间的核心区别是啥?哪些代码可以写成片段?

VSCode自定义代码片段——.vue文件的模板