NOIP模擬64
阿新 • • 發佈:2021-09-29
T1:
考場上以為是數論題,想推性質,然而並不會,於是考慮60分
考慮發現數據範圍中k <= 40,考慮模數很小,那麼考慮計數問題的經典
解決方法——對映,考慮在1~k範圍內求解,在反射回原值域,範圍可以通過
不等式限制
正解並不是數論,而是資料結構維護,考慮類似排列,我們通過列舉
一維來解決限制,便於維護,通常以列舉中間量,可以限制出左右兩側變數
於是列舉b,發現一個很優秀的性質為a為一次,於是a + b^2的範圍即可確定
,那麼考慮c的貢獻(即落到多少區間內),邊更新邊計算即可,樹狀陣列
區間修改單點查詢
程式碼如下:
1 #include <bits/stdc++.h> 2View Codeusing 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 }
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