bzoj4724--数论

题目大意:

B进制数,每个数字i(i=0,1,...,B-1)有a[i]个。你要用这些数字组成一个最大的B进制数X(不能有前导零,不需要
用完所有数字),使得X是B-1的倍数。q次询问,每次询问X在B进制下的第k位数字是什么(最低位是第0位)。
 
思路:
由于如下定理:
a*Bk≡a (mod (B-1) )
 
于是只要使所有位之和是(B-1)的倍数就可以了。又注意到a[i]>=1,只需删去sum%(B-1)就可以了。
询问用二分。
 
代码:
 #include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define ll long long
char buf[],*p1=buf,*p2=buf;
inline char Nc(){
if(p1==p2)p2=(p1=buf)+fread(buf,,,stdin);
return *p1++;
}
inline void Read(ll& x){
char c=Nc();
for(;c<''||c>'';c=Nc());
for(x=;c>=''&&c<='';x=(x<<)+(x<<)+c-,c=Nc());
}
inline void Read(int& x){
char c=Nc();
for(;c<''||c>'';c=Nc());
for(x=;c>=''&&c<='';x=(x<<)+(x<<)+c-,c=Nc());
}
int i,j,n,m;
ll a[],k,Sum;
inline int Find(ll k){
int l=,r=n-,Mid;
while(l<=r){
Mid=l+r>>;
if(a[Mid]>=k)r=Mid-;else l=Mid+;
}
return l;
}
char s[];
int Len;
inline void Print(int x){
if(x==){
puts("");
return;
}
for(Len=;x;x/=)s[++Len]=x%;
for(;Len;)putchar(s[Len--]+);
puts("");
}
int main()
{
Read(n);Read(m);
for(i=;i<n;i++)Read(a[i]),Sum=Sum+a[i]*i;
if(Sum%(n-))a[Sum%(n-)]--;
for(i=;i<n;i++)a[i]+=a[i-];
while(m--){
Read(k);
if(++k>a[n-])puts("-1");else Print(Find(k));
}
}

bzoj4724

上一篇:No_1 手写Proxy


下一篇:【C#小知识】C#中一些易混淆概念总结(六)---------解析里氏替换原则,虚方法 分类: C# 2014-02-08 01:53 1826人阅读 评论(0) 收藏