题目链接:https://atcoder.jp/contests/abc156/tasks/abc156_f
题目大意
给定$k$个数:$d_0,d_1,...,d_{k - 1}$。
再给出$q$条询问,每条询问给出$n, x, m$三个数,并按以下规则生成$a_0,a_1,...,a_{n - 1}$序列:
$$
egin{eqnarray}
a_j = egin{cases}x & ( j = 0 ) \ a_{j - 1} + d_{(j - 1)~ extrm{mod}~k} & ( 0 < j leq n - 1 )end{cases}
end{eqnarray}
$$
求满足$(a_j~ extrm{mod}~m) < (a_{j + 1}~ extrm{mod}~m)$的$j$的个数。
分析
首先,先让$d_i = d_i~ extrm{mod}~m$,容易看出,这并不会影响答案。
设$ltcnt$为满足$(a_j~ extrm{mod}~m) < (a_{j + 1}~ extrm{mod}~m)$的$j$的个数。
设$gtcnt$为满足$(a_j~ extrm{mod}~m) > (a_{j + 1}~ extrm{mod}~m)$的$j$的个数。
设$eqcnt$为满足$(a_j~ extrm{mod}~m) == (a_{j + 1}~ extrm{mod}~m)$的$j$的个数。
题目要求的是$ltcnt$,但好像不太好求。反过来想一想,我们如果求出了$gtcnt$和$eqcnt$,$ltcnt$不就出来了吗!
对于$eqcnt$,即求$d_{j~ extrm{mod}~k} == 0$的个数。
对于$gtcnt$,如果$(a_j~ extrm{mod}~m) > (a_{j + 1}~ extrm{mod}~m)$成立,那么必然有$(frac{a_j}{m} + 1) == frac{a_{j + 1}}{m}$,因此只要计算一下$frac{a_0}{m}$到$frac{a_{n - 1}}{m}$增长了多少即可。
代码如下
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 /*-------------------Define Start-------------------*/ 5 typedef bool BL; // 布尔类型 6 typedef char SB; // 有符号1字节,8位 7 typedef unsigned char UB; // 无符号1字节,8位 8 typedef short SW; // 有符号短整型,16位 9 typedef unsigned short UW; // 无符号短整型,16位 10 typedef long SDW; // 有符号整型,32位 11 typedef unsigned long UDW; // 无符号整型,32位 12 typedef long long SLL; // 有符号长整型,64位 13 typedef unsigned long long ULL; // 无符号长整型,64位 14 typedef char CH; // 单个字符 15 typedef float R32; // 单精度浮点数 16 typedef double R64; // 双精度浮点数 17 18 #define Rep(i, n) for (register SDW i = 0; i < (n); ++i) 19 #define For(i, s, t) for (register SDW i = (s); i <= (t); ++i) 20 #define rFor(i, t, s) for (register SDW i = (t); i >= (s); --i) 21 #define foreach(i, c) for (__typeof(c.begin()) i = c.begin(); i != c.end(); ++i) 22 #define ms0(a) memset(a,0,sizeof(a)) 23 #define msI(a) memset(a,0x7f,sizeof(a)) 24 #define LOWBIT(x) ((x)&(-x)) 25 26 #define MP make_pair 27 #define PB push_back 28 #define ft first 29 #define sd second 30 #define ALL(x) x.begin(),x.end() 31 32 #define pr(x) cout << #x << " = " << x << " " 33 #define prln(x) cout << #x << " = " << x << endl 34 35 const ULL mod = 1e9 + 7; //常用模数(可根据题目需要修改) 36 const ULL inf = 0x7fffffff; //用来表示无限大 37 const ULL infLL = 0x7fffffffffffffffLL; //用来表示无限大 38 39 // 重载<<操作符,用来打印vector 40 template < typename T > 41 ostream& operator<< (ostream& out, vector< T > vec) { 42 foreach(i, vec) { 43 if(i != vec.begin()) { 44 out << " "; 45 } 46 out << *i; 47 } 48 return out; 49 } 50 /*-------------------Define End-------------------*/ 51 52 const UDW maxN = 5e3 + 7; 53 SDW k, q; 54 SLL d[maxN], dm[maxN]; 55 SLL n, x, m; 56 SLL eqcnt; // 记录 a[i] % m == a[i+1] % m 的个数 57 SLL gtcnt; // 记录 a[i] % m > a[i+1] % m 的个数 58 SLL ltcnt; // 记录 a[i] % m < a[i+1] % m 的个数 59 SLL firstA; // a[0] 60 SLL lastA; // a[n-1] 61 SLL ans; 62 63 void input(){ 64 eqcnt = gtcnt = ltcnt = ans = 0; 65 cin >> n >> x >> m; 66 } 67 68 void solve(){ 69 firstA = lastA = x; 70 71 Rep(i, k) { 72 dm[i] = d[i] % m; 73 lastA += ((n - 1) / k) * dm[i]; 74 if(i < (n - 1) % k) { 75 lastA += dm[i]; 76 } 77 gtcnt += lastA / m; 78 lastA %= m; 79 } 80 81 Rep(i, k) { 82 if(dm[i] == 0) { 83 eqcnt += (n - 1) / k; 84 if(i < (n - 1) % k) { 85 ++eqcnt; 86 } 87 } 88 } 89 90 gtcnt -= firstA / m; 91 ltcnt = n - 1 - eqcnt - gtcnt; 92 93 ans = ltcnt; 94 } 95 96 void output(){ 97 cout << ans << endl; 98 } 99 100 int main() { 101 cin >> k >> q; 102 Rep(i, k) { 103 cin >> d[i]; 104 } 105 while(q--) { 106 input(); 107 solve(); 108 output(); 109 } 110 return 0; 111 }