题解:
假设 X 为 amam-1am-2……a1a0 每个 a 代表在 n 进制下第 i 位的数
那对于这个数而言其模 n - 1 的值也就是将每位相加再对于这个和取模
证明:
a0*n0%mod+a1*n1%mod+a2*n2%mod……
将其分解,就变成 ( ∑ i = 0 m a i ) % m o d (~\sum\limits_{i=0}^{m}a_i)\%mod ( i=0∑mai)%mod
因为 n k ≡ 1 ( % ( n − 1 ) ~n^k~\equiv 1~(~\%~(~n~-~1~) nk ≡1 ( % ( n − 1 )
而对于取模后多出来的值,将其删掉即可
因为由题目数据可知每一位上一定有数
但我当时没看到,还去一位一位删 T-T
而每次查询就用二分即可
Code
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <queue>
#include <cmath>
#define LL long long
#define ull unsigned LL //要加 LL
#define db double
#define ldb long db
#define INF 1000000009
using namespace std;
const LL N=1e6+100,M=1e5+100;
LL b,q,x,num,a[N],s[N];
bool fg;
LL find ( LL x )
{
LL wz=lower_bound ( s,s+b,x )-s;
return wz==b?-1:wz;
}
void print ( )
{
for ( LL i=0;i<b;i++ ) s[i]=s[max ( ( LL ) 0,i-1 )]+a[i];
while ( q-- )
{
scanf ( "%lld",&x );
printf ( "%lld\n",find ( ++x ) );
}
}
int main ( )
{
scanf ( "%lld %lld",&b,&q );
for ( LL i=0;i<b;i++ ) scanf ( "%lld",&a[i] ),num+=a[i]*i;
num%=( b-1 );
// for ( LL i=0;i<b;i++ ) printf ( "%lld ",s[i] );
// printf ( "\n" );
// printf ( "%lld\n",num );
if ( !num ) { print ( );return 0; }
for ( LL i=b-1;i>=0;i-- )
{
// printf ( "%lld\n",i );
if ( !num ) { fg=1;break; }
if ( !a[i] ) continue;
while ( i<=num && a[i] ) num-=i,a[i]--;
}
if ( fg ) print ( );
else printf ( "sbsbsb" );
return 0;
}
/*
9 7
0 1 0 1 0 2 0 1 2
1 2 3 4 5 6 7
*/
原代码