五月の诈尸笔记

最近状态超差。省赛惶恐。

强行插队的后果就是主刀沉迷考研副刀沉迷英语辅助沉迷力学。

趁着马上到来的公费旅游调养一下生息。然而马上要考试了。

 

5.7

xdu 1158 Orz Fatality

不是很懂数学。

 1 #include <iostream>
 2 #include <cstdio>
 3 using namespace std;
 4 typedef long long LL;
 5 const LL mod = 1e9 + 7;
 6 const int maxn = 1e7 + 10;
 7 LL fac[maxn];
 8 
 9 LL qpow(LL a, int b)
10 {
11     LL ret = 1LL;
12     while(b)
13     {
14         if(b & 1) ret = ret * a % mod;
15         a = a * a % mod;
16         b >>= 1;
17     }
18     return ret;
19 }
20 
21 LL inv(LL x)
22 {
23     return qpow(x, mod - 2);
24 }
25 
26 int main(void)
27 {
28     fac[0] = 1LL;
29     for(int i = 1; i < maxn; i++) fac[i] = fac[i-1] * i % mod;
30     LL x, y, k;
31     while(~scanf("%lld %lld %lld", &x, &y, &k))
32     {
33         if(k > y) puts("0");
34         else if(k == y) puts("1");
35         else
36         {
37             if(x + y >= maxn || x + k >= maxn) while(1);
38             LL ans = fac[x+y] * inv(fac[x+k]) % mod * inv(fac[y-k]) % mod;
39             printf("%lld\n", ans);
40         }
41     }
42     return 0;
43 }
Aguin

 

xdu 1148 修理OJ II

不是很懂数学again。

不懂题解最后一步怎么推的后来自己CRT出来式子不太一样也过了。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <algorithm>
 4 #include <cmath>
 5 using namespace std;
 6 typedef long long LL;
 7 
 8 LL Eular(LL n)
 9 {
10     LL ret = n;
11     for(LL i = 2; i * i <= n; i++)
12     {
13         if(n % i == 0)
14         {
15             ret -= ret / i;
16             while(n % i == 0) n /= i;
17         }
18     }
19     if(n > 1) ret -= ret / n;
20     return ret;
21 }
22 
23 LL qpow(LL a, LL b)
24 {
25     LL ret = 1LL;
26     while(b)
27     {
28         if(b & 1) ret = ret * a;
29         a = a * a;
30         b >>= 1;
31     }
32     return ret;
33 }
34 
35 LL qpow(LL a, LL b, LL mod)
36 {
37     LL ret = 1LL;
38     while(b)
39     {
40         if(b & 1) ret = ret * a % mod;
41         a = a * a % mod;
42         b >>= 1;
43     }
44     return ret;
45 }
46 
47 int main(void)
48 {
49     LL a, b, c, y;
50     while(~scanf("%lld %lld %lld %lld", &a, &b, &c, &y))
51     {
52         LL tmp = a, f = y, g = 1LL, t0 = 0LL;
53         for(LL i = 2; i * i <= tmp; i++)
54         {
55             if(tmp % i == 0)
56             {
57                 LL c1 = 0, c2 = 0;
58                 while(tmp % i == 0) tmp /= i, c1++;
59                 while(f % i == 0) f /= i, g *= i, c2++;
60                 t0 = max(t0, (c2 + c1 - 1) / c1);
61             }
62         }
63         if(tmp > 1)
64         {
65             LL c2 = 0;
66             while(f % tmp == 0) f /= tmp, g *= tmp, c2++;
67             t0 = max(t0, c2);
68         }
69         if(log(b) < log(t0) / c)
70         {
71             LL e = qpow(b, c);
72             printf("%lld\n", qpow(a, e, y));
73         }
74         else
75         {
76             LL pf = Eular(f);
77             LL ans = qpow(a, qpow(b, c, pf), y) * qpow(g, pf, y) % y;
78             printf("%lld\n", ans);
79         }
80     }
81     return 0;
82 }
Aguin

 

5.8

HDU 3037 Saving Beans

bin神模板。

 1 // HDU 3037 Saving Beans
 2 #include <iostream>
 3 #include <cstdio>
 4 using namespace std;
 5 typedef long long LL;
 6 const int maxn = 1e5 + 10;
 7 LL fac[maxn];
 8 
 9 LL qpow(LL a, LL b, LL mod)
10 {
11     LL ret = 1LL;
12     while(b)
13     {
14         if(b & 1) ret = ret * a % mod;
15         a = a * a % mod;
16         b >>= 1;
17     }
18     return ret;
19 }
20 
21 LL inv(LL x, LL mod)
22 {
23     return qpow(x, mod - 2, mod);
24 }
25 
26 LL Lucas(LL n, LL m, LL mod)
27 {
28     LL ret = 1LL;
29     while(n && m)
30     {
31         LL a = n % mod, b = m % mod;
32         if(a < b) return 0;
33         ret = ret * fac[a] % mod * inv(fac[b] * fac[a-b] % mod, mod) % mod;
34         n /= mod, m /= mod;
35     }
36     return ret;
37 }
38 
39 int main(void)
40 {
41     int T;
42     scanf("%d", &T);
43     while(T--)
44     {
45         LL n, m, p;
46         scanf("%I64d %I64d %I64d", &n, &m, &p);
47         fac[0] = 1LL;
48         for(int i = 1; i <= p; i++) fac[i] = fac[i-1] * i % p;
49         printf("%I64d\n", Lucas(n+m, n, p));
50     }
51     return 0;
52 }
Aguin

 

xdu 1057 卡尔的技能

原来叫 可重复组合数 阿。

 1 #include <iostream>
 2 #include <cstdio>
 3 using namespace std;
 4 typedef long long LL;
 5 const int maxn = 1e4 + 10;
 6 const LL mod = 10007;
 7 LL fac[maxn];
 8 
 9 LL qpow(LL a, LL b)
10 {
11     LL ret = 1LL;
12     while(b)
13     {
14         if(b & 1) ret = ret * a % mod;
15         a = a * a % mod;
16         b >>= 1;
17     }
18     return ret;
19 }
20 
21 LL inv(LL x)
22 {
23     return qpow(x, mod - 2);
24 }
25 
26 LL Lucas(LL n, LL m)
27 {
28     LL ret = 1LL;
29     while(n && m)
30     {
31         LL a = n % mod, b = m % mod;
32         if(a < b) return 0;
33         ret = ret * fac[a] % mod * inv(fac[b] * fac[a-b] % mod) % mod;
34         n /= mod, m /= mod;
35     }
36     return ret;
37 }
38 
39 int main(void)
40 {
41     fac[0] = 1LL;
42     for(int i = 1; i <= mod; i++) fac[i] = fac[i-1] * i % mod;
43     LL n, m;
44     while(~scanf("%lld %lld", &n, &m)) printf("%lld\n", Lucas(n+m-1, m));
45     return 0;
46 }
Aguin

 

5.10

PKU CAMPUS 2016 D Extracurricular Sports

不懂构造。昂神思路。bin神模板。

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <algorithm>
  5 using namespace std;
  6 const int MAXN = 9999;
  7 const int MAXSIZE = 1010;
  8 const int DLEN = 4;
  9 
 10 class BigNum
 11 {
 12 private:
 13     int a[500]; //可以控制大数的位数
 14     int len;
 15 public:
 16     BigNum() {len = 1; memset(a, 0, sizeof(a));} //构造函数
 17     BigNum(const int); //将一个int类型的变量转化成大数
 18     BigNum(const char *); //将一个字符串类型的变量转化为大数
 19     BigNum(const BigNum &); //拷贝构造函数
 20     BigNum & operator = (const BigNum &); //重载赋值运算符,大数之间进行赋值运算
 21     friend istream & operator >> (istream &, BigNum &); //重载输入运算符
 22     friend ostream & operator << (ostream &, BigNum &); //重载输出运算符
 23     BigNum operator + (const BigNum &)const; //重载加法运算符,两个大数之间的相加运算
 24     BigNum operator - (const BigNum &)const; //重载减法运算符,两个大数之间的相减运算
 25     BigNum operator * (const BigNum &)const; //重载乘法运算符,两个大数之间的相乘运算
 26     BigNum operator / (const int &)const; //重载除法运算符,大数对一个整数进行相除运算
 27     BigNum operator ^ (const int &)const; //大数的n次方运算
 28     int operator % (const int &)const; //大数对一个int类型的变量进行取模运算
 29     bool operator > (const BigNum & T)const; //大数和另一个大数的大小比较
 30     bool operator > (const int & t)const; //大数和一个int类型的变量的大小比较
 31     void print(); //输出大数
 32 };
 33 
 34 BigNum::BigNum(const int b) //将一个int类型的变量转化为大数
 35 {
 36     int c, d = b;
 37     len = 0;
 38     memset(a, 0, sizeof(a));
 39     while(d > MAXN)
 40     {
 41         c = d - (d / (MAXN + 1)) * (MAXN + 1);
 42         d = d / (MAXN + 1);
 43         a[len++] = c;
 44     }
 45     a[len++] = d;
 46 }
 47 
 48 BigNum::BigNum(const char * s) //将一个字符串类型的变量转化为大数
 49 {
 50     int t, k, index, L, i;
 51     memset(a, 0, sizeof(a));
 52     L = strlen(s);
 53     len = L / DLEN;
 54     if(L % DLEN) len++;
 55     index = 0;
 56     for(i = L - 1; i >= 0; i -= DLEN)
 57     {
 58         t = 0;
 59         k = i - DLEN + 1;
 60         if(k < 0) k = 0;
 61         for(int j = k; j <= i; j++)
 62             t = t * 10 + s[j] - '0';
 63         a[index++] = t;
 64     }
 65 }
 66 
 67 BigNum::BigNum(const BigNum & T): len(T.len) //拷贝构造函数
 68 {
 69     int i;
 70     memset(a, 0, sizeof(a));
 71     for(i = 0; i < len; i++)
 72         a[i] = T.a[i];
 73 }
 74 
 75 BigNum & BigNum::operator = (const BigNum & n) //重载赋值运算符,大数之间赋值运算
 76 {
 77     int i;
 78     len = n.len;
 79     memset(a, 0, sizeof(a));
 80     for(i = 0; i < len; i++)
 81     a[i] = n.a[i];
 82     return * this;
 83 }
 84 
 85 istream & operator >> (istream & in, BigNum & b)
 86 {
 87     char ch[MAXSIZE*4];
 88     int i = -1;
 89     in >> ch;
 90     int L = strlen(ch);
 91     int count = 0, sum = 0;
 92     for(i = L - 1; i >= 0; )
 93     {
 94         sum = 0;
 95         int t = 1;
 96         for(int j = 0; j < 4 && i >= 0; j++, i--, t *= 10)
 97         {
 98             sum += (ch[i] - '0') * t;
 99         }
100         b.a[count] = sum;
101         count++;
102     }
103     b.len = count++;
104     return in;
105 }
106 
107 ostream & operator << (ostream & out, BigNum & b) //重载输出运算符
108 {
109     int i;
110     cout << b.a[b.len-1];
111     for(i = b.len - 2; i >= 0; i--)
112     {
113         printf("%04d", b.a[i]);
114     }
115     return out;
116 }
117 
118 BigNum BigNum::operator + (const BigNum & T) const //两个大数之间的相加运算
119 {
120     BigNum t(*this);
121     int i, big;
122     big = T.len > len ? T.len : len;
123     for(i = 0; i < big; i++)
124     {
125         t.a[i] += T.a[i];
126         if(t.a[i] > MAXN)
127         {
128             t.a[i+1]++;
129             t.a[i] -= MAXN + 1;
130         }
131     }
132     if(t.a[big] != 0)
133     t.len = big + 1;
134     else t.len = big;
135     return t;
136 }
137 
138 BigNum BigNum::operator - (const BigNum & T) const //两个大数之间的相减运算
139 {
140     int i, j, big;
141     bool flag;
142     BigNum t1, t2;
143     if(*this > T)
144     {
145         t1 = *this;
146         t2 = T;
147         flag = 0;
148     }
149     else
150     {
151         t1 = T;
152         t2 = *this;
153         flag = 1;
154     }
155     big = t1.len;
156     for(i = 0; i < big; i++)
157     {
158         if(t1.a[i] < t2.a[i])
159         {
160             j = i + 1;
161             while(t1.a[j] == 0)
162                 j++;
163             t1.a[j--]--;
164             while(j > i)
165                 t1.a[j--] += MAXN;
166             t1.a[i] += MAXN + 1 - t2.a[i];
167         }
168         else t1.a[i] -= t2.a[i];
169     }
170     t1.len = big;
171     while(t1.a[len-1] == 0 && t1.len > 1)
172     {
173         t1.len--;
174         big--;
175     }
176     if(flag)
177         t1.a[big-1] = 0 - t1.a[big-1];
178     return t1;
179 }
180 
181 BigNum BigNum::operator * (const BigNum & T) const //两个大数之间的相乘
182 {
183     BigNum ret;
184     int i, j, up;
185     int temp, temp1;
186     for(i = 0; i < len; i++)
187     {
188         up = 0;
189         for(j = 0; j < T.len; j++)
190         {
191             temp = a[i] * T.a[j] + ret.a[i+j] + up;
192             if(temp > MAXN)
193             {
194                 temp1 = temp - temp / (MAXN + 1) * (MAXN + 1);
195                 up = temp / (MAXN + 1);
196                 ret.a[i+j] = temp1;
197             }
198             else
199             {
200                 up = 0;
201                 ret.a[i+j] = temp;
202             }
203         }
204         if(up != 0)
205             ret.a[i+j] = up;
206     }
207     ret.len = i + j;
208     while(ret.a[ret.len-1] == 0 && ret.len > 1) ret.len--;
209     return ret;
210 }
211 
212 BigNum BigNum::operator / (const int & b) const //大数对一个整数进行相除运算
213 {
214     BigNum ret;
215     int i, down = 0;
216     for(i = len - 1; i >= 0; i--)
217     {
218         ret.a[i] = (a[i] + down * (MAXN + 1)) / b;
219         down = a[i] + down * (MAXN + 1) - ret.a[i] * b;
220     }
221     ret.len = len;
222     while(ret.a[ret.len-1] == 0 && ret.len > 1)
223     ret.len--;
224     return ret;
225 }
226 
227 int BigNum::operator % (const int & b) const //大数对一个 int类型的变量进行取模
228 {
229     int i, d = 0;
230     for(i = len - 1; i >= 0; i--)
231         d = ((d * (MAXN + 1)) % b + a[i]) % b;
232     return d;
233 }
234 
235 BigNum BigNum::operator ^ (const int & n) const //大数的n次方运算
236 {
237     BigNum t, ret(1);
238     int i;
239     if(n < 0) exit(-1);
240     if(n == 0) return 1;
241     if(n == 1) return *this;
242     int m = n;
243     while(m > 1)
244     {
245         t = *this;
246         for(i = 1; (i << 1) <= m; i <<= 1)
247         t = t * t;
248         m -= i;
249         ret = ret * t;
250         if(m == 1) ret = ret * (*this);
251     }
252     return ret;
253 }
254 
255 bool BigNum::operator > (const BigNum & T) const //大数和另一个大数的大小比较
256 {
257     int ln;
258     if(len > T.len) return true;
259     else if(len == T.len)
260     {
261         ln = len - 1;
262         while(a[ln] == T.a[ln] && ln >= 0)
263             ln--;
264         if(ln >= 0 && a[ln] > T.a[ln])
265             return true;
266         else
267             return false;
268     }
269     else
270         return false;
271 }
272 
273 bool BigNum::operator > (const int & t) const //大数和一个int类型的变量的大小比较
274 {
275     BigNum b(t);
276     return *this > b;
277 }
278 
279 void BigNum::print() //输出大数
280 {
281     int i;
282     printf("%d", a[len-1]);
283     for(i = len - 2; i >= 0; i--)
284         printf("%04d", a[i]);
285     printf("\n");
286 }
287 
288 int main(void)
289 {
290     int T;
291     scanf("%d", &T);
292     while(T--)
293     {
294         int n;
295         scanf("%d", &n);
296         if(n == 2) {puts("-1"); continue;}
297         BigNum N[300];
298         BigNum two = BigNum(2), three = BigNum(3);
299         N[1] = BigNum(1), N[2] = two, N[3] = three;
300         if(n >= 4) N[3] = BigNum(6), N[4] = BigNum(9);
301         for(int i = 5; i <= n; i++)
302         {
303             for(int j = 3; j < n; j++) N[j] = N[j] * two;
304             N[i] = three;
305         }
306         for(int i = 1; i <= n; i++) N[i].print();
307     }
308     return 0;
309 }
Aguin

 

5.12

PKU CAMPUS 2016 H Magical Balls

昨天式子推错坑一天。今天还好发现是lld了。不然又要坑一天。

num[i+1] = num[i] * (u[i+1] + d[i+1] + l[i+1] + r[i+1] + 1)

sum[i+1] = sum[i] * (u[i+1] + d[i+1] + l[i+1] + r[i+1] + 1) + num[i] * (u[i+1] + r[i+1] - l[i+1] - d[i+1])

矩乘压一下。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 using namespace std;
 5 typedef long long LL;
 6 const LL mod = 1e9 + 7;
 7 const int maxn = 3;
 8 
 9 struct Matrix
10 {
11     LL m[maxn][maxn];
12     Matrix(){memset(m, 0, sizeof(m));}
13     void E(){for(int i = 0; i < maxn; i++) m[i][i] = 1;}
14 };
15 
16 Matrix M_mul(Matrix a, Matrix b)
17 {
18     Matrix ret;
19     for(int i = 0; i < maxn; i++)
20         for(int j = 0; j < maxn; j++)
21             for(int k = 0; k < maxn; k++)
22                 ret.m[i][j] = ( ret.m[i][j] + (a.m[i][k] * b.m[k][j]) % mod ) % mod;
23     return ret;
24 }
25 
26 Matrix M_qpow(Matrix P, LL n)
27 {
28     Matrix ret;
29     ret.E();
30     while(n)
31     {
32         if(n & 1LL) ret = M_mul(ret, P);
33         n >>= 1LL;
34         P = M_mul(P, P);
35     }
36     return ret;
37 }
38 
39 int main(void)
40 {
41     int T;
42     scanf("%d", &T);
43     while(T--)
44     {
45         LL N, M, x0, y0;
46         scanf("%lld %lld %lld %lld", &N, &M, &x0, &y0);
47         LL q = N / M, R = N % M;
48         Matrix A, B;
49         A.E(), B.E();
50         for(int i = 1; i <= M; i++)
51         {
52             LL u, d, l, r;
53             scanf("%lld %lld %lld %lld", &u, &d, &l, &r);
54             Matrix tmp;
55             tmp.m[1][1] = tmp.m[2][2] = (u + r + d + l + 1LL) % mod;
56             tmp.m[2][1] = (u + r - d - l + mod) % mod;
57             A = M_mul(tmp, A);
58             if(i <= R) B = M_mul(tmp, B);
59         }
60         Matrix P = M_mul(B, M_qpow(A, q));
61         LL ans = (P.m[2][1] + (x0 % mod + y0 % mod + mod + mod) % mod * P.m[2][2] % mod) % mod;
62         printf("%lld\n", ans);
63     }
64     return 0;
65 }
Aguin

 

5.13

BZOJ 2301 [HAOI2011]Problem b

不是很懂数学。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <algorithm>
 5 using namespace std;
 6 const int maxn = 1e6 + 10;
 7 int np[maxn], pr[maxn], mu[maxn];
 8 int sum[maxn];
 9 
10 void Mobius()
11 {
12     memset(np, 0, sizeof(np));
13     mu[1] = 1;
14     int tot = 0;
15     for(int i = 2; i < maxn; i++)
16     {
17         if(!np[i])
18         {
19             pr[tot++] = i;
20             mu[i] = -1;
21         }
22         for(int j = 0; j < tot; j++)
23         {
24             if(i * pr[j] >= maxn) break;
25             np[i*pr[j]] = 1;
26             if(i % pr[j] == 0)
27             {
28                 mu[i*pr[j]] = 0;
29                 break;
30             }
31             else mu[i*pr[j]] = -mu[i];
32         }
33     }
34 }
35 
36 int cal(int n, int m)
37 {
38     int ret = 0, pre;
39     if(n > m) swap(n, m);
40     for(int i = 1; i <= n; i = pre + 1)
41     {
42         pre = min(n / (n / i), m / (m / i));
43         ret += (n / i) * (m / i) * (sum[pre] - sum[i-1]);
44     }
45     return ret;
46 }
47 
48 int main(void)
49 {
50     Mobius();
51     for(int i = 1; i < maxn; i++) sum[i] = sum[i-1] + mu[i];
52     int n;
53     scanf("%d", &n);
54     while(n--)
55     {
56         int a, b, c, d, k;
57         scanf("%d %d %d %d %d", &a, &b, &c, &d, &k);
58         int ans = cal(b / k, d / k) - cal(b / k, (c - 1) / k) - cal((a - 1) / k, d / k) + cal((a - 1) / k, (c - 1) / k);
59         printf("%d\n", ans);
60     }
61     return 0;
62 }
Aguin

 

5.17

HZAU 1015 LCS

抄标程。

先预处理f[i][j]为a串前i,b串前j的最长公共后缀。

要求的是dp[i][j]为a串前i,b串前j的每部分不小于k的LCS。

这个不好直接推。所以引入一个opt[i][j][p]为取了a串i位置,b串j位置结尾,往前长度为p的一个公共串的LCS。

考虑opt的转移。如果p大于k,那么最优的opt其实就是前面取了i-1,j-1位置,后面再加一个相同字符。

①转移式是opt[i][j][p] = opt[i-1][j-1][p-1]+1,然后就可以枚举所有大于k的p推这个。

再考虑p等于k,这时opt[i-1][j-1][p-1]就没有了。

相当于i-k,j-k的答案我们已经算好了,后面又加上一段k的公共串。

②转移式是opt[i][j][k] = dp[i-k][j-k] + k。

 

上面因为要枚举p,复杂度就n^3爆炸了。于是把opt这个状态压一压。

opt[i][j]表示取a串i位置,b串j位置结尾,p取遍所有大于等于k的数的最优值。

(这里的opt[i][j]相当于上面的max{opt[i][j][p]}取遍p)

那么同样的分两类转移,如果i,j位置的f等于k,那么只能按②转移。即opt[i][j] = dp[i-k][j-k] + k。

如果f>k,考虑②同时也要考虑①,即opt[i][j] = opt[i-1][j-1] + 1。两者取优。

 

opt算好了。就可以推dp了。

如果i,j位置不取,那么相当于没有,此时dp[i][j] = max(dp[i-1][j], dp[i][j-1])。

如果取了,就是dp[i][j] = opt[i][j],也是两者取优。

 

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 using namespace std;
 5 int k, f[2222][2222], dp[2222][2222], opt[2222][2222];
 6 char a[2222], b[2222];
 7 
 8 int main(void)
 9 {
10     while(~scanf("%s %s %d", a + 1, b + 1, &k))
11     {
12 
13         memset(f, 0, sizeof(f));
14         memset(dp, 0, sizeof(dp));
15         memset(opt, 0, sizeof(opt));
16 
17         int la = strlen(a + 1), lb = strlen(b + 1);
18 
19         for(int i = 1; i <= la; i++)
20             for(int j = 1; j <= lb; j++)
21                 f[i][j] = (a[i] == b[j]) ? (f[i-1][j-1] + 1) : 0;
22 
23         for(int i = 1; i <= la; i++)
24         {
25             for(int j = 1; j <= lb; j++)
26             {
27                 if(f[i][j] >= k)
28                 {
29                     opt[i][j] = max(opt[i][j], dp[i-k][j-k] + k);
30                     if(f[i][j] > k) opt[i][j] = max(opt[i][j], opt[i-1][j-1] + 1);
31                 }
32                 dp[i][j] = max(opt[i][j], max(dp[i-1][j], dp[i][j-1]));
33             }
34         }
35 
36         printf("%d\n", dp[la][lb]);
37     }
38     return 0;
39 }
Aguin

 

posted @ 2016-05-07 20:43  Aguin  阅读(396)  评论(0编辑  收藏  举报