开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第3天,点击查看活动详情
A
A
题意:
已知小明妈妈的年龄求小明的年龄
题解:
推公式呀:妈妈为x,设小明为y
可以得到
y = a*x+b
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
void solve()
{
ll a,b,c;
cin >> a >> b >> c;
cout << (c - b) / a << '\n';
}
int main()
{
int t = 1;
//scanf("%d",&t);
while(t--)
{
solve();
}
}
B
题意:
m个房间,n个出口,不能走到罪犯的房间,所以相减一下就好了
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 500000 + 10;
ll a[100010];
void solve()
{
ll n,m,q;
cin >> n >> m >> q;
for(int i = 1;i <= n;i ++)
{
int x;
cin >> x;
a[x]++;
}
while(q--)
{
ll x;
cin >> x;
cout << n - a[x] << '\n';
}
}
int main()
{
int t = 1;
//scanf("%d",&t);
while(t--)
{
solve();
}
}
C
2000,找最大,直接dp(dp学的好烂,还好这个不难呜呜呜)
f存距离。就是找到i前面满足条件的最大距离+本身
状态转移方程:f[i] = max(f[i],f[j]+a[i]);
对了要注意一下并不是最后一个f[n]最大,不要忘记他还有一个条件相隔距离大于k
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 20010;
ll a[N], f[N];
int main()
{
int t = 1;
while(t--)
{
ll n, k;
scanf("%lld %lld",&n,&k);
for (int i = 1; i <= n; i ++)
scanf("%lld",&a[i]);
ll ans = 0;
for (int i = 1; i <= n; i ++)
{
f[i] = max(f[i], a[i]);
for(int j = 1;j + k < i;j ++)
{
f[i] = max(f[j]+ a[i],f[i]);
}
ans = max(f[i],ans);
}
printf("%lld\n",ans);
}
}
D
最小距离,好bfs,可是我是sb他一直报内存超限,我找不到错哪了,最后才发现这个不能开long long(呜呜呜,痛,太痛了)
大家应该都会bfs,注意是状态,他要求必须带超过x的刺激度,所以他可能会重复走一些格子,这个时候我们可以开三维,前两维表示坐标,最后一位表示状态。因为他的刺激度是交换,不是相加,所以我们可以在输入的时候判断一下,如果他大于0并且小于等于x那么全为0,那么剩下来的就是-1,走不了,0,已经>0要去的地方,这样我们可以吧状态压到2种,一种0,需要去找商店,一种1,已经去了商店去目的地就可以了
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 2011;
int n,m,h;
int f[N][N][2];
int s[N][N];
int x,y,xx,yy;
struct now{
int xxx;
int yyy;
int num;
int cnt;
};
queue<now>q;
int dx[4] = {0,0,1,-1};
int dy[4] = {1,-1,0,0};
void bfs()
{
q.push({x,y,0,0});
f[x][y][0] = 1;
while(q.size())
{
//printf("-1\n");
auto [a,b,c,d] = q.front();
q.pop();
for(int i = 0;i < 4;i ++)
{
int a1 = a+dx[i];
int b1 = b+dy[i];
int z = s[a1][b1];
int rx = max(s[a1][b1],c);
int w = 0;
if(rx > 0)
w = 1;
if(z < 0)
continue;
if(a1 < 1 || a1 > n || b1 < 1 || b1 > m)
continue;
if(f[a1][b1][w])
continue;
//cout << a1 <<' ' << b1 << ' '<< rx << ' ' << w << '\n';
if(a1 == xx && b1 == yy && rx > h )
{
printf("%d\n",d+1);
return ;
}
q.push({a1,b1,rx,d+1});
f[a1][b1][w] = 1;
}
}
printf("-1\n");
return ;
}
int main()
{
scanf("%d %d %d",&n,&m,&h);
scanf("%d %d %d %d",&x,&y,&xx,&yy);
for(int i = 1;i <= n;i ++)
for(int j = 1;j <= m;j ++)
{
scanf("%d",&s[i][j]);
if(s[i][j] <= h && s[i][j] > 0)
s[i][j] = 0;
}
bfs();
}
E
一看并查集吧,还好不是带权并查集(呜呜呜,这个搞不懂),但是判断素数需要欧拉筛搞一下,然后有木有发现两个都含那么直接求他们的gcd,再判断一下从1~gcd(x,y)之间有多少的质数可以整除gcd(x,y)
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 5e6 + 10;
ll a[N],c[N],d[N];
ll n;
int prime[N];
bool vis[N];
int cnt=0;
ll pos[N];
int find(int ans)
{
if(d[ans]!=ans)
d[ans] = find(d[ans]);
return d[ans];
}
void solve()
{
scanf("%lld",&n);
for(int i = 1;i <= n;i ++)
{
scanf("%lld",&a[i]);
d[i] = i;
}
int x,y;
for(int i = 1;i < n;i ++)
{
cin >> x >> y;
ll res = __gcd(a[x],a[y]);
//res = 3;
if(!c[res])
{
ll cnt1 = 0;
for(int j = 0;prime[j]<= res;j ++)
{
if(res % prime[j] == 0)
{
cnt1 ++;
}
if(cnt1 >= 2)
{
d[find(x)]=find(y);
//cout << x << " " << y << '\n';
break;
}
}
}
}
ll ans = 0;
for(int i = 1;i <= n;i ++)
{
ans = max(ans,++pos[find(i)]);
}
cout << ans << '\n';
}
int main()
{
int t = 1;
//scanf("%d",&t);
for(int i=2;i<=5e6;++i)
{
if(!vis[i])
{prime[cnt++]=i;vis[i]=true;}//vis[i]置为true或不置true都可以
for(int j=0;j<cnt;++j)
{
if(i*prime[j]>5e6)//判断是否越界
break;
vis[i*prime[j]]=true;//筛数
if(i%prime[j]==0)//时间复杂度为O(n)的关键!
break;
}
}
prime[0] = 2;
for(int i = 1;i <= cnt;i ++)//这个不能少,不然会超时,就是把所有的质数存起来放到后面判断
{
c[prime[i]] = 1;
}
while(t--)
{
solve();
}
}
F
实力不够,哭死(难受)