C、小红的数组构造(思维)
一、题目要求
链接:登录—专业IT笔试面试备考平台_牛客网
来源:牛客网
题目描述
小红想让你构造一个长度为 n 的数组,满足以下三个条件:
1. 该数组最大值不超过 k。
2. 该数组所有数都不相同。
3. 数组所有数之和等于 x。
输入描述:
输入一行三个正整数 n,k,x,用空格隔开。 1≤n≤10^5 1≤k≤x≤10^14
输出描述:
如果无法构造,请输出-1。 否则输出 n 个正整数,用空格隔开,代表构造的数组。有多解时输出任意即可。
示例1
输入
4 6 15
输出
1 3 6 5
示例2
输入
2 2 2
输出
-1
说明
显然无法构造出两个不相等的正整数和为2。
二、思路
1.先初始化数组
for(i=1;i<=n;i++)a[i]=i;x=x-i;
2.判断
(1)当有n个不同的数的时候,此时若从1开始,则最大值为n,当n比给定的k要大的时候则不符合条件
(2)当x<0的时候,则说明(1+n)*n/2 大于x,也不符合条件
3.倒着循环找差值,并将差值加到相应的数组中
4.如果经过3操作后,x等于0,则说明新创造的数组符合条件,当x!=0的时候,则说明不符合条件。
三、代码
#include<bits/stdc++.h>
#define endl '\n'
#define int long long
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
using namespace std;
const int N=2e5+10;
const int inf=0x3f3f3f3f;
int n,k,x;
int a[N];
void solve()
{cin>>n>>k>>x;int i,j;for(i=1;i<=n;i++){a[i]=i;x=x-i;}if(x<0||n>k){cout<<"-1"<<endl;return;}for(i=n;i>=1;i--){int y=min(x,k-a[i]);if(y<0)y=0;x-=y;a[i]+=y;k=a[i]-1;}if(x!=0){cout<<"-1"<<endl;return ;}for(i=1;i<=n;i++){cout<<a[i]<<' '; }cout<<endl;
}
signed main()
{IOS;int t=1;while(t--){solve();}return 0;
}
D、小红的图上删边(并查集)
一、题目要求
链接:登录—专业IT笔试面试备考平台_牛客网
来源:牛客网
题目描述
小红拿到了一个n个节点、m条边的无向连通图,每个节点的权值已知。
小红删掉一条边时,可以获得连接该边的两个节点“权值乘积末尾0数量”的价值。例如,一条边连接的两个点权值是50和60,那么小红删掉这条边获得的价值为3。
小红想知道,在保证这张图连通的情况下,最多可以通过删边获得多少价值?
输入描述:
第一行输入两个正整数 n 和 m,代表图的点数和边数。 第二行输入 n个正整数 aii,代表每个点的权值。 接下来的 m 行,每行输入两个正整数 u 和 v,代表点 u 和点 v 有一条边连接。 保证图连通,且无重边,无自环。 2≤n≤10^5 n−1≤m≤min(10^5,n∗(n−1)2) 1≤ai≤10^14 1≤u,v≤n
输出描述:
一个整数,代表删边可以获得的最大价值。
示例1
输入
3 3 5 8 25 1 2 2 3 1 3
输出
2
说明
删掉第二条边,由于8*25=200,末尾有2个零,所以可以获得2的价值。
二、思路
1.创建结构体u,v,w;
即:从u到v的权值为w
2.利用while()求出2的个数和5的个数,取两者最小值,则为w的值;
累加所有w的值则为cnt;
3. 对结构体里面的w从小到大排序,初始化并查集,利用find()函数,
在合并的过程中,累加w的值为s,当合并的个数为n-1的时候,跳出即可
4.则通过删边,获得的最大价值为 cnt-s
三、代码
#include<bits/stdc++.h>
#define endl '\n'
#define int long long
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
using namespace std;
const int N=2e5+10;
const int inf=0x3f3f3f3f;
int n,m;
int fa[N],a[N];
struct node
{int u,v,w;
}q[N];
bool cmp(node l,node r)
{return l.w<r.w;
}
int find(int x)
{if(fa[x]==x)return x;return fa[x]=find(fa[x]);
}
void solve()
{cin>>n>>m;int i,j;int cnt=0;for(i=1;i<=n;i++){cin>>a[i];}for(i=1;i<=m;i++){cin>>q[i].u>>q[i].v;int sum1=0,sum2=0;int cc=a[q[i].u];while(cc%2==0) sum1++,cc/=2;while(cc%5==0) sum2++,cc/=5;int bb=a[q[i].v];while(bb%2==0) sum1++,bb/=2;while(bb%5==0) sum2++,bb/=5;q[i].w=min(sum1,sum2);//取2和5个数的最小值,即0的个数 cnt+=q[i].w;}sort(q+1,q+m+1,cmp);for(i=1;i<=n;i++)//并查集:初始化 {fa[i]=i;} int cntt=0,s=0;for(i=1;i<=m;i++){if(find(q[i].u)!=find(q[i].v)){fa[find(q[i].u)]=find(q[i].v);s+=q[i].w;cntt++;}if(cntt==n-1)break;} cout<<cnt-s<<endl;
}
signed main()
{int t=1;while(t--){solve();}return 0;
}