1. 程式人生 > >Podzielno

Podzielno

stat img 數據 整除 組成 lib 一個 位數 event

問題 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\n"); else { ll pos; pos=lower_bound(sum,sum+B,k+1)-sum; printf("%lld\n",pos); } } return 0; }
View Code

Podzielno