1. 程式人生 > 其它 >NOIP模擬64

NOIP模擬64

T1:

  考場上以為是數論題,想推性質,然而並不會,於是考慮60分

考慮發現數據範圍中k <= 40,考慮模數很小,那麼考慮計數問題的經典

解決方法——對映,考慮在1~k範圍內求解,在反射回原值域,範圍可以通過

不等式限制

  正解並不是數論,而是資料結構維護,考慮類似排列,我們通過列舉

一維來解決限制,便於維護,通常以列舉中間量,可以限制出左右兩側變數

於是列舉b,發現一個很優秀的性質為a為一次,於是a + b^2的範圍即可確定

,那麼考慮c的貢獻(即落到多少區間內),邊更新邊計算即可,樹狀陣列

區間修改單點查詢

程式碼如下:

 1 #include <bits/stdc++.h>
 2
using namespace std; 3 #define I long long 4 #define C char 5 #define B bool 6 #define V void 7 #define D double 8 #define LL long long 9 #define UI unsigned int 10 #define UL unsigned long long 11 #define P pair 12 #define MP make_pair 13 #define a first 14 #define b second 15 #define debug cout << "It's Ok Here !" << endl; 16
#define lowbit(x) (x & -x) 17 #define FP(x) freopen (#x,"r",stdin) 18 #define FC(x) freopen (#x,"w",stdout) 19 const I N = 1e5 + 3; 20 I T,n,t; 21 inline I read () { 22 I x(0),y(1); C z(getchar()); 23 while (!isdigit(z)) { if (z == '-') y = -1; z = getchar(); } 24 while ( isdigit(z)) x = x * 10
+ (z ^ 48), z = getchar(); 25 return x * y; 26 } 27 inline V Max (I &a,I b) { a = a > b ? a : b; } 28 inline V Min (I &a,I b) { a = a < b ? a : b; } 29 inline I max (I a,I b) { return a > b ? a : b; } 30 inline I min (I a,I b) { return a < b ? a : b; } 31 inline V swap (I &a,I &b) { a ^= b, b ^= a, a ^= b; } 32 inline I abs (I a) { return a >= 0 ? a : -a; } 33 inline P<I,I> operator + (const P<I,I> &a,const P<I,I> &b) { 34 return MP (a.a + b.a,a.b + b.b); 35 } 36 inline P<I,I> operator - (const P<I,I> &a,const P<I,I> &b) { 37 return MP (a.a - b.a,a.b - b.b); 38 } 39 struct BIT { 40 I c[N]; 41 inline V secmod (I x,I y) { 42 for (;x <= t;x += lowbit (x)) 43 c[x] ++ ; 44 for (;y <= t;y += lowbit (y)) 45 c[y] -- ; 46 } 47 inline I preque (I x) { I ans(0); 48 for (; x ;x -= lowbit (x)) 49 ans += c[x]; 50 return ans; 51 } 52 }B1; 53 signed main () { 54 FP (exclaim.in), FC (exclaim.out); 55 T = read(); 56 for (I i(1);i <= T; ++ i) { 57 printf ("Case %d: ",i); 58 n = read(), t = read(); I tmp(0); LL ans(0); 59 for (I j(1);j <= n; ++ j) { 60 I l((j * j + 1) % t + 1), 61 r((j * j + j) % t + 1); 62 if (j >= t) tmp += j / t - (r + 1 == l) - (r - l + 1 == t); 63 if (l <= r) B1.secmod (l,r + 1); 64 if (l > r) B1.secmod (1,r + 1), B1.secmod (l,t + 1); 65 I last (ans); 66 ans += tmp + B1.preque (j * j * j % t + 1); 67 } 68 printf ("%lld\n",ans); 69 memset (B1.c,0,sizeof B1.c); 70 } 71 }
View Code

T2:

  首先看錯題目暴斃,要求迴圈同構,於是首先簡單的想法為n^2列舉區間

那麼考慮如何O(1)判斷迴圈同構,字串匹配一種常見的方法顯然為雜湊

然而並不能應對迴圈,考慮剪枝,這裡應用到字符集優化,即通過字符集雜湊

首先判斷兩端字元是否相等,在進行迴圈判斷,可以通過此題,再通過map記錄

可以應對Hack資料

程式碼如下:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 #define I int
 4 #define C char
 5 #define B bool
 6 #define V void
 7 #define D double
 8 #define LL long long
 9 #define UI unsigned int
10 #define UL unsigned long long
11 #define P pair
12 #define MP make_pair
13 #define a first
14 #define b second
15 #define debug cout << "It's Ok Here !" << endl;
16 #define lowbit(x) (x & -x)
17 #define FP(x) freopen (#x,"r",stdin)
18 #define FC(x) freopen (#x,"w",stdout)
19 const I N = 5e3 + 3;
20 I n,ans;
21 UL p[N],f[N],t[N];
22 inline I read () {
23     I x(0),y(1); C z(getchar());
24     while (!isdigit(z)) { if (z == '-') y = -1; z = getchar(); }
25     while ( isdigit(z))  x = x * 10 + (z ^ 48), z = getchar();
26     return x * y;
27 }
28 inline V Max (I &a,I b) { a = a > b ? a : b; }
29 inline V Min (I &a,I b) { a = a < b ? a : b; }
30 inline I max (I a,I b) { return a > b ? a : b; }
31 inline I min (I a,I b) { return a < b ? a : b; }
32 inline V swap (I &a,I &b) { a ^= b, b ^= a, a ^= b; }
33 inline I abs (I a) { return a >= 0 ? a : -a; }
34 inline P<I,I> operator + (const P<I,I> &a,const P<I,I> &b) {
35     return MP (a.a + b.a,a.b + b.b);
36 }
37 inline P<I,I> operator - (const P<I,I> &a,const P<I,I> &b) {
38     return MP (a.a - b.a,a.b - b.b);
39 }
40 inline B Check (I l,I r) {
41     I mid (l + r >> 1), len (r - l + 1 >> 1);
42     if (t[r] - t[mid] != t[mid] - t[l - 1]) return false;
43     UL com (f[r] - f[mid] * p[len]);
44     for (I i(l);i <= mid; ++ i) 
45         if ((f[mid] - f[i] * p[mid - i] - f[l - 1]) * p[i - l + 1] + f[i] == com)
46             return true;
47     return false;
48 }
49 signed main () {
50     FP (s.in), FC (s.out);
51     n = read(); p[0] = 1; 
52     for (I i(1);i <= 5000; ++ i)
53         p[i] = p[i - 1] * 13331;
54     for (I i(1),x,y;i <= n; ++ i) {
55         x = read();
56         t[i] = t[i - 1] + p[x];
57         f[i] = f[i - 1] * 13331 + x;
58         if (x == y) ans ++ ;  y = x;
59     }
60     for (I len(3);len <  n;len += 2) 
61       for (I i(1);i + len <= n; ++ i) {
62         if (Check (i,i + len)) ans ++ ;
63       }
64     printf ("%d\n",ans);
65 }
View Code