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),表示一个询问。
第二行包含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; }
以上是关于Podzielno的主要内容,如果未能解决你的问题,请参考以下文章
BZOJ4724[POI2017]Podzielno 数学+二分