本场链接:AtCoder Beginner Contest 215
闲话
感觉有些不在状态,傻逼题都做不出来,脑子想不进去.GH不知道能不能做,能做再说.
A - Your First Judge
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define forn(i,x,n) for(int i = x;i <= n;++i)
#define forr(i,x,n) for(int i = n;i >= x;--i)
#define Angel_Dust ios::sync_with_stdio(0);cin.tie(0)
int main()
{
string s;cin >> s;
if(s == "Hello,World!") cout << "AC
";
else cout << "WA
";
return 0;
}
B - log2(N)
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define forn(i,x,n) for(int i = x;i <= n;++i)
#define forr(i,x,n) for(int i = n;i >= x;--i)
#define Angel_Dust ios::sync_with_stdio(0);cin.tie(0)
int main()
{
ll n;cin >> n;
int res = 0;
forn(k,0,62) if((1ll << k) <= n) res = k;
printf("%d
",res);
return 0;
}
C - One More aab aba baa
注意去重.
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define forn(i,x,n) for(int i = x;i <= n;++i)
#define forr(i,x,n) for(int i = n;i >= x;--i)
#define Angel_Dust ios::sync_with_stdio(0);cin.tie(0)
const int N = 100;
char s[N];
int d[N];
int main()
{
int k;scanf("%s%d",s + 1,&k);int n = strlen(s + 1);
forn(i,1,n) d[i] = i;
vector<string> all;
do
{
string cur;
forn(i,1,n) cur += s[d[i]];
all.push_back(cur);
} while (next_permutation(d + 1,d + n + 1));
sort(all.begin(),all.end());all.erase(unique(all.begin(),all.end()),all.end());
cout << all[k - 1] << endl;
return 0;
}
D - Coprime 2
正难则反:考虑所有会有(gcd(a_i,k) = d)且(d eq 1)的(k).显然这样的(k)是(a_i)的一个约数(d)的若干倍.那么枚举出所有(a_i)的约数,并且把这些约数自己和所有约数的倍数全部打上标记,被标记的点就是存在(gcd(a_i,k) = d)且(d eq 1)的(k).如此,统计最后没有被标记的数即可.
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define forn(i,x,n) for(int i = x;i <= n;++i)
#define forr(i,x,n) for(int i = n;i >= x;--i)
#define Angel_Dust ios::sync_with_stdio(0);cin.tie(0)
const int N = 1e5+7;
bool st[N];
int main()
{
int n,m;scanf("%d%d",&n,&m);
forn(i,1,n)
{
int a;scanf("%d",&a);
for(int d = 1;1ll * d * d <= a;++d)
{
if(a % d != 0) continue;
st[d] = 1;
st[a / d] = 1;
}
}
st[1] = 0;
forn(i,2,N - 1)
{
if(!st[i]) continue;
for(int j = i;j <= N - 1;j += i) st[j] = 1;
}
vector<int> res;
forn(i,1,m) if(!st[i]) res.push_back(i);
printf("%d
",(int)res.size());
for(auto& _ : res) printf("%d
",_);
return 0;
}
E - Chain Contestant
因为$ |sum| = 10$考虑状压:
- (f[i][j][k])表示做完第(i)个位置,当前已经选出的元素集合是(j)且末尾元素是(k)的方案数.
- 入口:(f[i][(1 << s_i)][s_i] = 1).
- 转移:若不放入 (s_i) 显然 $ += f[i - 1][j][k]$ ;若放入 (s_i),可能会有两种情况:要么(s_i)是第一次出现在序列里,作为起点;要么(s_i)是接到当前已经有的屁股后面,显然这个已经有的必须是当前的末尾.如果是接到后面,让(f[i][j][k] += f[i - 1][j][k]),此时需要满足(k == j).反过来如果(k)不属于(j)集合,那么此时放入(s_i)就是作为一个新的起点:(f[i][j | (1 << s_i)][k] += sum_{z eq k} f[i - 1][j][z]).(在具体实现的时候,如果转移方程是正确的,那么(z == k)的时候也不会有问题,因为(j)里面不包含(k)的情况下方案数是(0))
- 出口:(res = sum_{j,k} f[n][j][k]).
入口可以不直接写出,在转移时给加一即可.
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define forn(i,x,n) for(int i = x;i <= n;++i)
#define forr(i,x,n) for(int i = n;i >= x;--i)
#define Angel_Dust ios::sync_with_stdio(0);cin.tie(0)
const int N = 10,M = (1 << 10),C = 1020,MOD = 998244353;
int f[C][M][N];
char s[C];
int main()
{
int n;scanf("%d",&n);
scanf("%s",s);
forn(i,1,n)
{
int x = s[i - 1] - 'A';
forn(j,0,(1 << 10) - 1) forn(k,0,9)
{
f[i][j][k] = f[i - 1][j][k];
if(k == x) f[i][j][k] = (1ll * f[i][j][k] + f[i - 1][j][k]) % MOD;
}
forn(j,0,(1 << 10) - 1)
{
if(j >> x & 1) continue;
forn(k,0,9) f[i][j | (1 << x)][x] = (1ll * f[i][j | (1 << x)][x] + f[i - 1][j][k]) % MOD;
}
f[i][1 << x][x] = (f[i][1 << x][x] + 1) % MOD;
}
int res = 0;
forn(j,0,(1 << 10) - 1) forn(k,0,9) res = (res + f[n][j][k]) % MOD;
printf("%d
",res);
return 0;
}
F - Dist Max 2
使最小值最大,考虑二分答案:二分最终答案(ans geq L)?
(ans geq L) 等价于 (min(|x_i - x_j|,|y_i - y_j|) geq L),即 (|x_i - x_j| geq L,|y_i - y_j| geq L) 同时满足.
如此,check
函数等价于求解:对于每个位置 (i in [1,n - 1]),是否存在一个 (j in [i + 1,n]) 同时满足如上两个条件.如果把绝对值拆掉,可以得到四个不等式,满足其中一个不等式即可.由于((i,j))的相对次序可以忽略,可以将所有点按照 (x) 坐标上升排序,这样可以删掉其中两个,最后剩下: (x_j - x_i geq L && y_i - y_j geq L) 或 (x_j - x_i geq L && y_j - y_i geq L) 满足其一即可.
排序之后保证了一维偏序关系,剩下的一维偏序关系可以发现只需要找到:在某个后缀中(y)的最大值或最小值,因为要看是否存在一个 (j in [i + 1,n]) 满足 (y_j - y_i geq L) 那肯定取 (y_j) 的最大值.分别记作 (Rmin/Rmax).即可将 check
的复杂度做到 (O(nlogn)).
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
#define forn(i,x,n) for(int i = x;i <= n;++i)
#define forr(i,x,n) for(int i = n;i >= x;--i)
#define Angel_Dust ios::sync_with_stdio(0);cin.tie(0)
#define x first
#define y second
const int N = 2e5+7;
pii p[N];
int Rmin[N],Rmax[N];
int n;
bool check(int L)
{
forn(i,1,n - 1)
{
int pos = lower_bound(p + i + 2,p + n + 1,pii{p[i].x + L,0}) - p;
if(pos == n + 1) continue;
if(Rmax[pos] >= L + p[i].y || Rmin[pos] <= p[i].y - L) return 1;
}
return 0;
}
int main()
{
scanf("%d",&n);
forn(i,1,n) scanf("%d%d",&p[i].x,&p[i].y);
sort(p + 1,p + n + 1);
Rmin[n] = p[n].y;Rmax[n] = p[n].y;
forr(i,1,n - 1) Rmin[i] = min(Rmin[i + 1],p[i].y),Rmax[i] = max(Rmax[i + 1],p[i].y);
int l = 0,r = 2e9,idx = 0;
while(l < r)
{
int mid = l + r + 1 >> 1;
if(check(mid)) l = mid;
else r = mid - 1;
}
printf("%d
",l);
return 0;
}