比赛链接:牛客小白月赛60_ACM/NOI/CSP/CCPC/ICPC算法编程高难度练习赛_牛客竞赛OJ (nowcoder.com)
A: 小竹与妈妈
思路:简单数学题
代码:
#include<bits/stdc++.h>
#define int long long
#define fast ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
using namespace std;
const int N=2e5+10;
inline void solve(){
int a,b,c;cin>>a>>b>>c;
cout<<(c-b)/a<<"\n";
}
signed main(){
fast;
//int T;cin>>T;
//while(T--)
solve();
}
B:走丢的小竹
思路:统计每个点对应有多少个出口,因为当前坏人所在的位置所对应的出口是不能走的。所以总的方案数是除了坏人所占据的出口的所有出口数的和
代码:
#include<bits/stdc++.h>
#define int long long
#define fast ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
using namespace std;
const int N=2e5+10;
int cnt[N];
inline void solve(){
int n,m,q,maxx=0;cin>>n>>m>>q;
for(int i=1;i<=n;i++){
int x;cin>>x;
cnt[x]++;maxx=max(maxx,x);
}
int res=0;
for(int i=1;i<=maxx;i++) res+=cnt[i];
while(q--){
int x;cin>>x;
int ans=res-cnt[x];
cout<<ans<<"\n";
}
}
signed main(){
fast;
//int T;cin>>T;
//while(T--)
solve();
}
C:小竹关禁闭
思路:DP。我们考虑,DP【i】为取到第i个绳长所得到的最长长度。
代码:
#include<bits/stdc++.h>
#define int long long
#define fast ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
using namespace std;
const int N=2e5+10;
int a[N],dp[N];
inline void solve(){
int n,k;cin>>n>>k;
for(int i=1;i<=n;i++) cin>>a[i],dp[i]=a[i];
for(int i=1;i<=n;i++){
for(int j=i+k+1;j<=n;j++){
dp[j]=max(dp[j],dp[i]+a[j]);
}
}
int res=0;
for(int i=1;i<=n;i++) res=max(res,dp[i]);
cout<<res<<"\n";
}
signed main(){
fast;
//int T;cin>>T;
//while(T--)
solve();
}
D:游戏购买!
方法:BFS。首先BFS预处理求出起点和中间(小胖和小猪家)分别到每个商店的最短距离,然后枚举所有符合条件的商店位置,每个商店到两家的距离之和就是距离,所有这样的距离求和即可
代码:
#include<bits/stdc++.h>
#define int long long
#define fast ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
using namespace std;
const int N=2e3+10;
typedef pair<int,int> PII;
int a[N][N],dist1[N][N],dist2[N][N];
bool vis[N][N],pd[N][N];//pd:标记合法点位
int n,m,w,sx,sy,ex,ey;
int d[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
inline void solve(){
cin>>n>>m>>w>>sx>>sy>>ex>>ey;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
cin>>a[i][j];
}
}
queue<PII>q,qq;
dist1[sx][sy]=0;vis[sx][sy]=true;
q.push({sx,sy});
while(!q.empty()){
int x=q.front().first,y=q.front().second;
q.pop();
for(int i=0;i<4;i++){
int xx=x+d[i][0],yy=y+d[i][1];
if(xx<1||xx>n||yy<1||yy>m||vis[xx][yy]||a[xx][yy]==-1) continue;
dist1[xx][yy]=dist1[x][y]+1;vis[xx][yy]=true;
q.push({xx,yy});
if(a[xx][yy]>w) pd[xx][yy]=true;
}
}
memset(vis,false,sizeof vis);
int ans=1e9+10;
dist2[ex][ey]=0;vis[ex][ey]=true;
q.push({ex,ey});
while(!q.empty()){
int x=q.front().first,y=q.front().second;
q.pop();
for(int i=0;i<4;i++){
int xx=x+d[i][0],yy=y+d[i][1];
if(xx<1||xx>n||yy<1||yy>m||vis[xx][yy]||a[xx][yy]==-1) continue;
dist2[xx][yy]=dist2[x][y]+1;vis[xx][yy]=true;
q.push({xx,yy});
//合法点位到两目标点位的距离和
if(pd[xx][yy]) ans=min(ans,dist1[xx][yy]+dist2[xx][yy]);
q.push({xx,yy});
}
}
if(ans>1e8) cout<<"-1";
else cout<<ans;
}
signed main(){
fast;
//int T;cin>>T;
//while(T--)
solve();
}
E:寻找小竹!
分析:并查集+质数筛。读完题发现,我们需要建立一棵树。建树的规则:建立边的时候,需要判断一下边两头的节点是否互为优雅(最大公约数是否有至少两个不同的质因数)。利用并查集来进行合并节点,利用一个数组来维护连通块的大小。
并查集:并查集(基础)_Black_Chocolate.的博客-优快云博客
代码:
#include<bits/stdc++.h>
#define int long long
#define fast ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
using namespace std;
const int N=2e7;
int a[N],fa[N],sz[N],cnt[N];
//fa:代表i号节点的代表元 sz:维护联通块的大小 cnt:记录数字i的质因数个数
int find(int x){//查找节点的代表元
if(x==fa[x]) return x;
return fa[x]=find(fa[x]);
}
void solve(){
int n;cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];fa[i]=i;sz[i]=1;
}
for(int i=2;i<=n;i++){//质因子数筛
if(cnt[i]) continue;
for(int j=i;j<=1e7;j+=i){
cnt[j]++;
}
}
for(int i=1;i<n;i++){
int x,y;
cin>>x>>y;
int g=__gcd(a[x],a[y]);
if(cnt[g]>=2){//满足条件就合并节点
sz[find(y)]+=sz[find(x)];//维护大小
fa[find(x)]=find(y);//合并节点
}
}
int ans=0;
for(int i=1;i<=n;i++){
ans=max(ans,sz[find(i)]);//找最大值
}
cout<<ans<<'\n';
}
signed main(){
fast;
//int T;cin>>T;
//while(T--)
solve();
}
F:被抓住的小竹
ps:这是一道关于数论的题,目前还没有能力去解决,这里先附上一篇代码,自行理解一下吧。(以后待补题解)
代码:
#include<bits/stdc++.h>
#define int long long
#define fast ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
using namespace std;
const int N=2e7;
const int mod=1e9+7;
int a[N];
int power(int a,int b){//快速幂
int res=1;
while(b){
if(b&1) res=res*a%mod;
a=a*a%mod;
b>>=1;
}
return res;
}
int inv(int x){
return power(x,mod-2);
}
void solve(){
a[0]=1;
for(int i=1;i<=1e5+10;i++) a[i]=a[i-1]*i%mod;
int k;cin>>k;
while(k--){
int x;cin>>x;
cout<<(x*x%mod)*(x-1)%mod*a[x+3]%mod*inv(96)%mod<<"\n";//不理解qaq..0.0.
}
}
signed main(){
fast;
//int T;cin>>T;
//while(T--)
solve();
}