Gym102091
比赛时只写了CDGHJL
C
对二元组
(
a
i
,
i
)
(a_i, i)
(ai,i) 以
a
i
a_i
ai 为第一关键字,
i
i
i 为第二关键字升序排列,求最长的序列使得对任意
i
,
j
i, j
i,j 有
∣
i
−
j
∣
≤
w
|i-j| \leq w
∣i−j∣≤w。
直接dp即可,时间复杂度
O
(
n
2
)
O(n^2)
O(n2)
int n, w;
struct Node {
int a, idx, cnt;
bool operator < (const Node &x) const {
return a < x.a;
}
}node[maxn];
void solve() {
cin >> n >> w;
for(int i = 1; i <= n; i++) {
cin >> node[i].a;
node[i].idx = i;
}
sort(node + 1, node + n + 1);
int ans = 0;
for(int i = 1; i <= n; i++) {
for(int j = 1; j < i; j++) {
if(abs(node[j].idx - node[i].idx) <= w && node[i].a > node[j].a) {
node[i].cnt = max(node[i].cnt, node[j].cnt + 1);
ans = max(ans, node[i].cnt);
}
}
}
cout << ans << endl;
}
D
签到,贪心即可
int n;
int a[maxn];
void solve() {
cin >> n;
if(n == 0) {
cout << 0 << endl;
return;
}
for(int i = 1; i <= n; i++) cin >> a[i];
int cnt = 1;
int p = a[1] + 10;
for(int i = 1; i <= n; i++) {
if(a[i] > p + 10) {
cnt++;
p = a[i] + 10;
}
}
cout << cnt << endl;
}
G
强连通分量板子,队友写的
vector<int> vec[205];
int dfn[205],low[205];
int cnt=0;
int s[205],scc[205];
int tmp=0,num=0;
void tarjan(int x){
dfn[x]=low[x]=++cnt;
s[++tmp]=x;
for(int i=0;i<vec[x].size();i++)
{
int u=vec[x][i];
if(!dfn[u]){
tarjan(u);
low[x]=min(low[x],low[u]);
}else if(!scc[u]){
low[x]=min(low[x],dfn[u]);
}
}
if(dfn[x]==low[x]){
num++;
while(tmp){
int p=s[tmp--];
scc[p]=num;
if(p==x)break;
}
}
}
void solve() {
int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++)vec[i].clear();
for(int i=1;i<=m;i++)
{
int u,v;
cin>>u>>v;
u++,v++;
vec[u].push_back(v);
}
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));
memset(s,0,sizeof(s));
memset(scc,0,sizeof(scc));
cnt=0,tmp=0,num=0;
for(int i=1;i<=n;i++)if(!dfn[i])tarjan(i);
cout<<num<<'\n';
}
H
题意
给出
a
,
b
,
c
a, b, c
a,b,c 和
x
3
m
o
d
a
,
x
3
m
o
d
b
,
x
3
m
o
d
c
x^3\ mod\ a,x^3\ mod\ b, x^3\ mod\ c
x3 mod a,x3 mod b,x3 mod c 的值,求
x
x
x 其中
a
,
b
,
c
<
2
21
a, b, c < 2^{21}
a,b,c<221。
不知道正解怎么做的,直接从 1 到
2
21
2^{21}
221 枚举 x,满足上面三个式子即是答案。不知道为什么x一定在这个范围内。
LL exgcd(LL a, LL b, LL &x, LL &y) {
if(!b) {x = 1; y = 0; return a;}
LL d = exgcd(b, a%b, x, y);
LL z = x; x = y; y = z - y * (a / b);
return d;
}
ll inv(ll a, ll p) {
ll x, y;
exgcd(a, p, x, y);
return (x % p + p) % p;
}
ll mul(ll a, ll b, ll p) {
LL ans = 0;
a %= p;
for (; b; b >>= 1) {
if (b & 1) ans = (ans + a) % p;
a = (a + a) % p;
}
return ans;
}
ll M;
ll excrt(ll m[], ll a[], ll n)
{
M=m[1];
ll ans=a[1];
for(int i=2;i<=n;++i)
{
ll k1,k2,g=exgcd(M,m[i],k1,k2);
if((a[i]-ans)%g)return -1; //判断是否无解
k1=(a[i]-ans)/g*k1%m[i];
ans+=k1*M;
M=M/g*m[i];
ans%=M;
}
return (ans-1+M)%M+1;
}
void solve() {
ll a[5];
ll b[5];
for(int i = 1; i <= 3; i++) cin >> a[i];
for(int i = 1; i <= 3; i++) cin >> b[i];
ll ans = excrt(a, b, 3);
int mx = (1 << 21);
for(int i = 1; i <= mx; i++) {
int now = i * i * i;
if(now - ans < 0) continue;
if((now - ans) % M == 0) {
cout << i << endl;
break;
}
}
}
J
题意
就是给出
l
o
w
,
h
i
g
h
low,high
low,high ,求这个式子的值,但题目明确表示直接模拟会有精度问题。
队友写了几分钟直接秒了orz,实际上就是求导。
#include <bits/stdc++.h>
#define int long long
using namespace std;
typedef long double ld;
signed main()
{
#ifdef DDD
freopen("input.txt", "r", stdin);
#endif
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
ld x, y;
while (cin >> x >> y && !(x==0&&y==0))
{
ld ans = 0.;
for (ld i=x; i<=y; ++i)
{
ld tmp;
tmp = pow(i, -(ld)2.0/3.0);
ans += tmp;
}
ans /= 3.0;
ans *= 1e-15;
string line, line2;
stringstream ss(line2);
ss << setprecision(5) << scientific;
ss << ans;
ss >> line;
line[7] = 'E';
if (line.size() == 10)
{
line = line + line[9];
line = line + line[9];
line[9] = '0';
line[10] = '0';
}
else if (line.size() == 11)
{
line = line + line[10];
line[10] = line[9];
line[9] = '0';
}
else
{
line[9] = line[line.size()-3];
line[10] = line[line.size()-2];
line[11] = line[line.size()-1];
line = line.substr(0, 12);
}
cout << line << '\n';
}
return 0;
}
L
题意
给出只包含0,1的
n
行
m
列
n行m列
n行m列矩阵,求最多包涵一个1的正方形的最大边长。
巨弱不会
O
(
n
2
)
O(n^2)
O(n2)做法,套了个二分答案
O
(
n
2
log
n
)
O(n^2\log n)
O(n2logn) 过的,不过都需要优化输入。
int n, m;
bool a[N][N];
int sum[N][N];
bool ok(int mid) {
if(mid == 1)
return true;
for(int i = mid; i <= n; i++) {
for(int j = mid; j <= m; j++) {
int i1 = i - mid;
int j1 = j - mid;
if(sum[i][j] + sum[i1][j1] - sum[i][j1]-sum[i1][j] <= 1) {
return true;
}
}
}
return false;
}
inline int read()
{
char ch = getchar();
int ans0 = 0;
while (!isdigit(ch))
{
ch = getchar();
}
while (isdigit(ch))
{
ans0 = ans0*10+ch-'0';
ch = getchar();
}
return ans0;
}
void solve() {
char c;
n = read();
m = read();
bool flag = 0;
for(int i = 1; i <= n; i++) {
for(int j =1 ; j <= m; j++) {
a[i][j] = read();
if(!a[i][j]) flag = 1;
sum[i][j] = sum[i-1][j] + sum[i][j-1] - sum[i-1][j-1] + a[i][j];
}
}
if(!flag) {
printf("1\n");
return;
}
int l = 1, r = min(n, m);
int ans = 1;
while(l <= r) {
int mid = (l + r) >> 1;
if(ok(mid)) {
ans = mid;
l = mid + 1;
}
else {
r = mid - 1;
}
}
printf("%d\n", ans);
}