2019-2020 ICPC Asia Taipei-Hsinchu Regional Contest 訓練記錄


solved:9/13

upsolved:9/13

A.

數據范圍很小,bfs + 去重就能過。注意出口只有一端。
  1 #include <bits/stdc++.h>
  2 
  3 using namespace std;
  4 
  5 const int N = 6;
  6 const int SEED = 31;
  7 
  8 int a[N][N];
  9 int m;
 10 set<uint64_t> f;
 11 
 12 struct Car {
 13     bool is_vertical;
 14     int lx, ly, rx, ry; // or upos dpos
 15     Car() : lx(INT_MAX), ly(INT_MAX), rx(0), ry(0) {}
 16 } p[10 + 5];
 17 
 18 struct Stat {
 19     int st[N][N];
 20     void copy() {
 21         memcpy(st, a, sizeof(a));
 22     }
 23     void paste() {
 24         memcpy(a, st, sizeof(a));
 25     }
 26     Stat() { memset(st, 0, sizeof(st)); }
 27 };
 28 
 29 uint64_t encode() {
 30     uint64_t seed = 0;
 31     for (int i = 0; i < N; ++i)
 32         for (int j = 0; j < N; ++j)
 33             seed = (seed + a[i][j]) * SEED;
 34     return seed;
 35 }
 36 
 37 void init_car() {
 38     for (int i = 1; i <= m; ++i)
 39         p[i] = Car();
 40     for (int i = 0; i < N; ++i)
 41         for (int j = 0; j < N; ++j) {
 42             int x = a[i][j];
 43             p[x].lx = min(p[x].lx, i);
 44             p[x].ly = min(p[x].ly, j);
 45             p[x].rx = max(p[x].rx, i);
 46             p[x].ry = max(p[x].ry, j);
 47             if (p[x].lx == p[x].rx)
 48                 p[x].is_vertical = false;
 49             if (p[x].ly == p[x].ry)
 50                 p[x].is_vertical = true;
 51         }
 52 }
 53 
 54 int bfs() {
 55     queue<pair<int, Stat> > que;
 56     Stat temp;
 57     temp.copy();
 58     que.push(make_pair(0, temp));
 59     while (!que.empty()) {
 60         int step = que.front().first;
 61         if (step > 8) {
 62             return -1;
 63         }
 64         if (a[2][5] == 1) {
 65             return step + 2;
 66             // cerr << "QWQ\n";
 67         }
 68         temp = que.front().second;
 69         que.pop();
 70         temp.paste();
 71         uint64_t code = encode();
 72         if (f.count(code))
 73             continue;
 74         f.insert(code);
 75         init_car();
 76         // do {
 77         //     cerr << "STEP: " << step << endl;
 78         //     for (int i = 0; i < N; ++i) {
 79         //         for (int j = 0; j < N; ++j) {
 80         //             cerr << a[i][j] << ' ';
 81         //         }
 82         //         cerr << endl;
 83         //     }
 84         //     cerr << endl;
 85         // } while (false);
 86         for (int t = 1; t <= m; ++t) {
 87             if (p[t].is_vertical) {
 88                 int lx = p[t].lx;
 89                 int rx = p[t].rx;
 90                 int y = p[t].ly;
 91                 if (0 < lx && a[lx - 1][y] == 0) {
 92                     a[lx - 1][y] = t;
 93                     a[rx][y] = 0;
 94                     temp.copy();
 95                     que.push(make_pair(step + 1, temp));
 96                     a[rx][y] = t;
 97                     a[lx - 1][y] = 0;
 98                 }
 99                 if (rx + 1 < N && a[rx + 1][y] == 0) {
100                     a[rx + 1][y] = t;
101                     a[lx][y] = 0;
102                     temp.copy();
103                     que.push(make_pair(step + 1, temp));
104                     a[lx][y] = t;
105                     a[rx + 1][y] = 0;
106                 }
107             } else {
108                 int x = p[t].lx;
109                 int ly = p[t].ly;
110                 int ry = p[t].ry;
111                 if (0 < ly && a[x][ly - 1] == 0) {
112                     a[x][ly - 1] = t;
113                     a[x][ry] = 0;
114                     temp.copy();
115                     que.push(make_pair(step + 1, temp));
116                     a[x][ly - 1] = 0;
117                     a[x][ry] = t;
118                 }
119                 if (ry + 1 < N && a[x][ry + 1] == 0) {
120                     a[x][ry + 1] = t;
121                     a[x][ly] = 0;
122                     temp.copy();
123                     que.push(make_pair(step + 1, temp));
124                     a[x][ry + 1] = 0;
125                     a[x][ly] = t;
126                 }
127             }
128         }
129     }
130     return -1;
131 }
132 
133 int main() {
134     ios::sync_with_stdio(false);
135     for (int i = 0; i < N; ++i)
136         for (int j = 0; j < N; ++j) {
137             cin >> a[i][j];
138             m = max(a[i][j], m);
139         }
140     init_car();
141     cout << bfs() << endl;
142 }
View Code

 

C.

簽到題

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int n;
 4 int a[55];
 5 int main()
 6 {
 7     scanf("%d",&n);
 8     for(int i=1;i<=n;++i)scanf("%d",&a[i]);
 9     bool yes=1;
10     for(int i=1;i<=n;++i)
11         for(int j=1;j<=n;++j)if(j!=i)
12             for(int k=1;k<=n;++k)if(k!=i&&k!=j)
13             {
14                 int x=abs(a[i]-a[j]);
15                 if(x%a[k])yes=0;    
16             }
17     if(yes)puts("yes");
18     else puts("no");
19 }
View Code

 

D.

簽到題

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 string s;
 4 int main()
 5 {
 6     bool has=0;
 7     while(cin>>s)
 8     {
 9         if(s=="bubble"||s=="tapioka")continue;
10         has=1;
11         cout<<s<<" "; 
12     }
13     if(!has)puts("nothing");
14 }
View Code

 

E.

構造一個長度1999的序列

考慮第一個數是負數,那么假算法一定不會包含這個數,取\(a_1=-1\)

序列為\(-1,a_2,a_3,…,a_{1999}\)

那么假算法的解為\(1998*\sum_{i=2}^{1999}{a_i}\)

真算法的解為\(1999*(\sum_{i=2}^{1999}{a_i}-1)\)

那么假算法的解比真算法小$k$,則有\(1999*(\sum_{i=2}^{1999}{a_i}-1)=1998*\sum_{i=2}^{1999}{a_i}+k\)

則有\(\sum_{i=2}^{1999}{a_i}=1999+k\)

隨便構造一下湊夠\(k\)就完事了

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int T,k,L;
 4 int main()
 5 {
 6     scanf("%d",&T);
 7     while(T--)
 8     {
 9         scanf("%d%d",&k,&L);
10         if(L>=2000)puts("-1");
11         else
12         {
13             puts("1999");
14             printf("-1 ");
15             int s=k+1999,x=1000000;
16             for(int i=1;i<=1998;++i)
17             {
18                 if(s>=x)
19                 {
20                     printf("%d ",x);
21                     s-=x;
22                 }
23                 else
24                 {
25                     printf("%d ",s);
26                     s=0;
27                 }
28             }
29         }
30     }
31 }
View Code

 

H.

考慮方程\(\frac{1}{x}+\frac{1}{y}=\frac{1}{n}\)

移項通分有\(\frac{1}{y}=\frac{x-n}{xn}\)

則\(y=\frac{xn}{x-n}\)

令\(a=x-n\),則有\(y=n+\frac{n^2}{a}\)

那么枚舉\(n^2\)的約數,解出\(x,y\)即可

然后\(a=x \oplus y\)

 1 #include<bits/stdc++.h>
 2 #define ll long long
 3 using namespace std;
 4 int T;
 5 ll n;
 6 int main()
 7 {
 8     cin>>T;
 9     while(T--)
10     {
11         cin>>n;
12         ll ans=0;
13         for(ll i=1;i<=n;++i)if((n*n)%i==0)
14         {
15             ll y=n+n*n/i;
16             ll x=n+i;
17             ll a=x^y;
18             ans=max(ans,a);
19         }
20         cout<<ans<<endl;
21     }
22 }
View Code

 

J.

二進制枚舉集合,簽到題

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int T,n,m;
 4 bitset<505> a[18];
 5 int main()
 6 {
 7     scanf("%d",&T);
 8     while(T--)
 9     {
10         scanf("%d%d",&n,&m);
11         for(int i=0;i<m;++i)
12         {
13             char str[505];
14             scanf("%s",str);
15             for(int j=0;j<n;++j)a[i][j]=0;
16             for(int j=0;j<n;++j)if(str[j]=='1')a[i][j]=1;
17         }
18         int ans=m+1;
19         for(int S=0;S<(1<<m);++S)
20         {
21             bitset<505> b;
22             for(int i=0;i<n;++i)b[i]=0;
23             int cnt=0;
24             for(int i=0;i<m;++i)if(S&(1<<i))b|=a[i],cnt++;
25             bool yes=1;
26             for(int i=0;i<n;++i)if(!b[i])yes=0;
27             if(yes)ans=min(ans,cnt);
28         }
29         if(ans<=m)printf("%d\n",ans);
30         else puts("-1");
31     }
32 }
View Code

 K.

簽到題。合並石子,優先隊列即可。
 1 #include <bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 int main() {
 6     ios::sync_with_stdio(false);
 7     int T;
 8     cin >> T;
 9     while (T--) {
10         int n;
11         cin >> n;
12         priority_queue<int, vector<int>, greater<int>> que;
13         for (int i = 0; i < n; ++i) {
14             int x;
15             cin >> x;
16             que.push(x);
17         }
18         int sum = 0;
19         while (!que.empty()) {
20             if (que.size() == 1) {
21                 cout << sum << endl;
22                 break;
23             }
24             int x = que.top();
25             que.pop();
26             int y = que.top();
27             que.pop();
28             sum += x + y;
29             que.push(x + y);
30         }
31     }
32 }
View Code

 

L.

因為可能是退化的四邊形,所以不能在凸包上直接找點

考慮四邊形的對角線一定是凸包上的對踵點,那么這步可以旋轉卡殼得到對踵點

我們下面不能直接在凸包上三分了,但本題允許\(O(n^2)\)的時間復雜度,那么我們枚舉點

四邊形可能是凹的,所以我們枚舉的時候需要分別記錄這條線兩邊最大最小的面積

如果某邊沒有點,就是最大減最小,否則就是兩邊相加

 1 #include<bits/stdc++.h>
 2 #define ll long long
 3 using namespace std;
 4 struct Point
 5 {
 6     ll x,y;
 7     Point(ll X=0,ll Y=0):x(X),y(Y){}
 8 };
 9 typedef Point Vector;
10 inline Vector operator + (Vector A,Vector B){return Vector(A.x+B.x,A.y+B.y);}
11 inline Vector operator - (Point A,Point B){return Vector(A.x-B.x, A.y-B.y);}
12 ll Cross(Vector A,Vector B){return A.x*B.y-A.y*B.x;}
13 bool operator < (Point A,Point B){if(A.x==B.x)return A.y<B.y;return A.x<B.x;}
14 bool operator == (Point A,Point B){return (A.x==B.x)&&(A.y==B.y);}
15 vector<Point> ConvexHull(vector<Point>& p)
16 {
17     sort(p.begin(),p.end());
18     p.erase(unique(p.begin(),p.end()),p.end());
19     int n=p.size();
20     int m=0;
21     vector<Point> ch(n+1);
22     for(int i=0;i<n;++i)
23     {
24         while(m>1&&Cross(ch[m-1]-ch[m-2],p[i]-ch[m-2])<=0)m--;
25         ch[m++]=p[i];
26     }
27     int k=m;
28     for(int i=n-2;i>=0;--i)
29     {
30         while(m>k&&Cross(ch[m-1]-ch[m-2],p[i]-ch[m-2])<=0)m--;
31         ch[m++]=p[i];
32     }
33     if(n>1)m--;
34     ch.resize(m);
35     return ch;
36 }
37 int T,n,m;
38 vector<Point> A,H;
39 ll calc(Point U,Point V,bool tst=0)
40 {
41     bool firU=0,firV=0;
42     vector<Point> B;B.clear();
43     for(Point p:A)
44     {
45         if(p==U&&(!firU))firU=1;
46         else if(p==V&&(!firV))firV=1;
47         else B.push_back(p);
48     }
49     ll mx1=-1,mx2=-1,mn1=(ll)2e18,mn2=(ll)2e18;
50     for(Point p:B)
51     {
52         //if(tst)printf("(%I64d,%I64d)\n",p.x,p.y);
53         if(Cross(V-U,p-U)<0)
54         {
55             mx1=max(mx1,abs(Cross(V-U,p-U)));
56             mn1=min(mn1,abs(Cross(V-U,p-U)));
57         }
58         else
59         {
60             mx2=max(mx2,abs(Cross(V-U,p-U)));
61             mn2=min(mn2,abs(Cross(V-U,p-U)));
62         }
63     }
64     if(mx1==-1)return mx2-mn2;
65     else if(mx2==-1)return mx1-mn1;
66     else return mx1+mx2;
67 }
68 int main()
69 {
70     scanf("%d",&T);
71     while(T--)
72     {
73         A.clear();
74         scanf("%d",&n);
75         for(int i=1;i<=n;++i)
76         {
77             ll x,y;
78             scanf("%I64d%I64d",&x,&y);
79             A.push_back(Point(x,y));
80         }
81         H=A;
82         H=ConvexHull(H);
83         m=H.size();
84         if(m<=2)
85         {
86             puts("0");
87             continue;
88         }
89         int j=1;
90         ll ans=0;
91         for(int i=0;i<m;++i)
92         {
93             while(abs(Cross(H[j]-H[i],H[j]-H[(i+1)%m]))<abs(Cross(H[(j+1)%m]-H[i],H[(j+1)%m]-H[(i+1)%m])))j=(j+1)%m;
94             ans=max(ans,calc(H[i],H[j]));
95         }
96         if(ans&1)printf("%I64d.5\n",ans/2);
97         else printf("%I64d\n",ans/2);
98     }
99 }
View Code

 M.

題意為求解$\dfrac{\binom{N}{M}}{D^k}$,其中$\binom{N}{M}$恰好整除$D^k$。

對$D$質因數分解,得$D=\prod_{i=0}p_i^{a_i}$。我們可以單獨求得每個$p^a$的答案,再用 CRT 合並即可。

當對於$p^a$求答案時,有:
$$ \binom{N}{M}=\frac{N!}{M!(N-M)!}=\frac{(N!/p^x)}{(M!)/p^y((N-M)!)/p^z}\cdot p^{-x+y+z} $$
答案為$\frac{(N!/p^x)}{(M!)/p^y((N-M)!)/p^z}$。考慮如何計算這個式子。

令$f(n)=\frac{n!}{p^h}$,其中$p^h\mid n!$且$p^{h+1}\nmid n!$,$g(n)=\prod_{i=1,d\nmid i}^{n}i$。類似 exlucas 方法,有
$$f(n)=f(\frac{n}{p})\cdot g(p)^{\frac{n}{p}}\cdot g(n\bmod p)$$
所以答案為
$$\dfrac{\binom{N}{M}}{D^k}=\dfrac{\binom{N}{M}/p^h\cdot p^{h-ka}}{\Big(\frac{D}{p^a}\Big)^k}$$
合並即可。
  1 #include <bits/stdc++.h>
  2 
  3 using namespace std;
  4 
  5 const int MAXD = 16000000 + 10;
  6 const int MAXN = 100000 + 10;
  7 
  8 int64_t qpow(int64_t a, int64_t b, int64_t p) {
  9     int64_t ans = 1;
 10     while (b) {
 11         if (b & 1)
 12             ans = ans * a % p;
 13         a = a * a % p;
 14         b >>= 1;
 15     }
 16     return ans;
 17 }
 18 
 19 void exgcd(int64_t a, int64_t b, int64_t& x, int64_t& y, int64_t& d) {
 20     if (!b)
 21         d = a, x = 1, y = 0;
 22     else
 23         exgcd(b, a % b, y, x, d), y -= a / b * x;
 24 }
 25 
 26 int64_t inv(int64_t a, int64_t p) {
 27     int64_t x, y, d;
 28     exgcd(a, p, x, y, d);
 29     x = (x % p + p) % p;
 30     return x;
 31 }
 32 
 33 
 34 int64_t N, M, D, K;
 35 int64_t a[MAXN], mi[MAXN], pi[MAXN], num[MAXN], ki[MAXN];
 36 int64_t n, g[MAXD];
 37 
 38 int64_t _cal(int64_t x, int64_t p) {
 39     int64_t ans = 0;
 40     while (x) {
 41         ans += x / p;
 42         x /= p;
 43     }
 44     return ans;
 45 }
 46 
 47 int64_t calc(int64_t p) {
 48     return _cal(N, p) - _cal(M, p) - _cal(N - M, p);
 49 }
 50 int64_t CRT() {
 51     int64_t Mi = 1, ans = 0, x, y, d;
 52     for (int i = 1; i <= n; ++i)
 53         Mi *= mi[i];
 54     for (int i = 1; i <= n; ++i) {
 55         exgcd(Mi / mi[i], mi[i], x, y, d);
 56         x = (x % mi[i] + mi[i]) % mi[i];
 57         ans = (ans + Mi / mi[i] * x % Mi * a[i] % Mi) % Mi;
 58     }
 59     return ans;
 60 }
 61 
 62 void factorize(int64_t x) {
 63     for (int64_t i = 2; i * i <= x; ++i) {
 64         if (x % i == 0) {
 65             num[++n] = 0;
 66             pi[n] = i;
 67             mi[n] = 1;
 68             while (x % i == 0) {
 69                 ++num[n];
 70                 x /= i;
 71                 mi[n] *= i;
 72             }
 73         }
 74     }
 75     if (x > 1) {
 76         num[++n] = 1;
 77         pi[n] = x;
 78         mi[n] = x;
 79     }
 80 }
 81 
 82 int64_t fact(int64_t n, int64_t x, int64_t p) {
 83     if (!n)
 84         return 1;
 85     int64_t ans = qpow(g[p], n / p, p) * g[n % p] % p;
 86     return ans * fact(n / x, x, p) % p;
 87 }
 88 
 89 int64_t C(int64_t x, int64_t p) {
 90     g[0] = 1;
 91     for (int64_t i = 1; i <= p; ++i) {
 92         g[i] = g[i - 1];
 93         if (i % x)
 94             g[i] = g[i] * i % p;
 95     }
 96     return fact(N, x, p) * inv(fact(M, x, p), p) % p
 97         * inv(fact(N - M, x, p), p) % p;
 98 }
 99 
100 int main() {
101     ios::sync_with_stdio(false);
102     cin >> N >> M >> D;
103     factorize(D);
104     K = LLONG_MAX;
105     for (int i = 1; i <= n; ++i) {
106         ki[i] = calc(pi[i]);
107         K = min(K, ki[i] / num[i]);
108     }
109     for (int i=  1; i <= n; ++i) {
110         a[i] = C(pi[i], mi[i]) * qpow(pi[i], ki[i] - K * num[i], mi[i]) % mi[i]
111             * qpow(inv(D / mi[i], mi[i]), K, mi[i]) % mi[i];
112     }
113     cout << CRT() << endl;
114 }
View Code

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM