div4 题解

前言:说实话codeforce不挂VPN是真的绝望,我是当时被人拎去在比赛时间做的,然后那吃屎的速度硬是只让我A了前5T,反正写题半小时等待半小时。

在这里插入图片描述
A. Sum of Round Numbers
题意:给出n个数,输出每个数有几位不是0,然后下一行输出分解后的数
1111->输出 4
1000 100 10 1

#include<bits/stdc++.h>
using namespace std;
int main(){
	int n;
	cin>>n;
	for(int i=1;i<=n;++i)
	{
		int a,ans[6],cnt=0,t=1; //因为数据最大为1e4,所以ans开到6足够
		cin>>a;
	    while(a)   //a为0说明分解完毕
	    {
	    	if(a%10==0)t*=10;
	    	else {ans[++cnt]=(a%10)*t;t*=10;}
	    	a/=10;
		}
		cout<<cnt<<endl;
		for(int i=1;i<=cnt;++i)
		{
			cout<<ans[i]<<" ";
		}
		cout<<endl;
	}
}

B. Same Parity Summands
题意:共 t组数据,每组给一个n一个k,把n拆成k个同奇或同偶的数
思路:偶数就k-1个为2,剩下的为n-2*(k-1),奇数就全为1,剩下的为n-k。
然后考虑可行和不可行的所有情况。

#include<bits/stdc++.h>
using namespace std;
int main()
{
	int n;
	cin>>n;
	while(n--)
	{
		int m,k;
		cin>>m>>k;
		if(m%2==1&&k%2==0){cout<<"NO"<<endl;continue;}
		if(m%2==0&&k%2==1&&m<k*2){cout<<"NO"<<endl;continue;}
		if(k%2==0&&m<k){cout<<"NO"<<endl;continue;}
		if(m%2==1&&k>m){cout<<"NO"<<endl;continue;}
		cout<<"YES"<<endl;
		if(k%2==1&&m%2==0){
			while(k!=1){
				cout<<2<<" ";
				m-=2;
				k--;
			}
			cout<<m<<endl;
			continue;
		}
		else if(k%2==0&&m%2==0){
			while(k!=1){
				cout<<1<<" ";
				m--;
				k--; 
			}
			cout<<m<<endl;
			continue;
		}
		if(m%2==1&&k%2==1){
			while(k!=1)
			{
				cout<<1<<" ";
				k--;
				m--;
			}
			cout<<m<<endl;
		}
	}
}

C. K-th Not Divisible by n(沙雕题,连水题都不配)
题意:t组数据,每组给出n和k,求第k个不能被n整除的数
思路;一个n为1环,每环满足条件的数有n-1个,所以用sum=n*k/(n-1),
如果k被(n-1)整除,就sum-1,不然就加上k%(n-1)

#include<bits/stdc++.h>
using namespace std;
int main()
{
	int n;
	cin>>n;
	while(n--)
	{
		int a,b,sum=0;
		cin>>a>>b;
		sum=b/(a-1)*a;
		if(b%(a-1)==0)sum-=1;
		else sum+=b%(a-1);
		cout<<sum<<endl;
	}
}

D. Alice, Bob and Candies
没啥好说的deque还不会用的拖出去打死

#include<bits/stdc++.h>
using namespace std;
int main()
{
	int n;
	cin>>n;
	while(n--)
	{
		int t,s1=0,s2=0,next=0,cnt=1;
		deque<int> p;
		cin>>t;
		for(int i=1;i<=t;++i)
		{
			int a;
			cin>>a;
			p.push_back(a);
		}
		next=p.front();
		p.pop_front();
		s1+=next;
		while(!p.empty())
		{
			int sum=0;
			++cnt;
			if(cnt%2==1){
				while(sum<=next&&!p.empty())
				{
					sum+=p.front();
					p.pop_front();
			    }
			    next=sum;
				s1+=sum;
				continue;
			}
			else{
				while(sum<=next&&!p.empty())
				{
					sum+=p.back();
					p.pop_back();
			    }
			    next=sum;
				s2+=sum;
				continue;
			}
		}
		cout<<cnt<<" "<<s1<<" "<<s2<<endl;
	}
}

E. Special Elements
题意:能不写吗 求n个数的数列中有几个数可以用连续子区间的和表示。(讲道理这个数据量,摆明了一副快来大力上我的意思
思路:前缀和优化使查找区间和的时复为O(1),桶排使查找同样的数的时复为O(1),然后逐渐增大区间,遍历。

#include<bits/stdc++.h>
using namespace std;
int max(int a,int b)
{
	if(a>b)return a;
	return b;
}
int main(){
	int n;
	cin>>n;
	while(n--){
		int a[8006]={0},s[8006]={0},sum[8006]={0},mx=0,cnt=0;
		int m;
		cin>>m;
		for(int i=1;i<=m;++i)
		{
			int a;
			cin>>a;
			s[a]++;
			mx=max(mx,a);
			sum[i]=sum[i-1]+a;
		}
		int l=2;
		while(l<m)
		{
			for(int i=l;i<=m;++i)
			{
				int b=sum[i]-sum[i-l];
				if(b<=mx)a[b]=1;
			}
			l++;
		}
		for(int i=2;i<=mx;++i){
			if(a[i])cnt+=s[i];
		}
		cout<<cnt<<endl;
	}
}

F. Binary String Reconstruction
题意:t组数据,每组给3个数n0,n1,n2,代表‘00’ ‘01’ ‘11’的字符个数
思路:(这道题我一开始抽风了,硬着头皮按先‘00’后‘01’再‘11’构造,然后我就烂了,wa了n发 )先构造00和11,如果n0和n2均不为0,n1-1,然后n1看前面的数是0还是1选择输出,如果没有数,那就自己造自己就完事

#include<bits/stdc++.h>
#define ll long long int
using namespace std;
int main(){
	int n;
	cin>>n;
	while(n--)
	{
		int a,b,c;
		cin>>a>>b>>c;
		if(c)
		{
			for(int i=1;i<=c+1;++i)
			{
				cout<<1;
			}
		}
		if(a)
		{
		for(int j=1;j<=a+1;++j)
		{
			cout<<0;
		}
		}
		if(a&&c)b--;
		if(a==0&&c)
		{
			for(int i=1;i<=b;++i)
			{
				cout<<(i%2==1?0:1);
			}
		}
		if(a){
			for(int i=1;i<=b;++i)
			{
				cout<<(i%2==1?1:0);
			}
		}
		if(a==0&&c==0)
		{
			cout<<1;
			for(int i=1;i<=b;++i)
			{
				cout<<(i%2==1?0:1);
			}
		}
		cout<<endl;
	}
}

G. Special Permutation
题意:输入n,将1到n排列,相邻数据之差为2到4
思路:奇数偶数分开排,然后其中一个队列按降序排列,我是偶数在前,
最后2和4换个位置,同理可得如果n<4,则不存在

#include<bits/stdc++.h>
using namespace std;
int main()
{
	int n;
	cin>>n;
	while(n--)
	{
		int a,b;
		cin>>a;
		if(a<4){cout<<-1<<endl;continue;}
		b=a;
		if(a%2==1)b=a-1;
		while(b>4)
		{
			cout<<b<<" ";
			b-=2;
		}
		if(b>4){cout<<2;cout<<" "<<4;}
		else cout<<2<<" "<<4;
		for(int i=1;i<=a;i+=2)
		{
			cout<<" "<<i;
		}
		cout<<endl;
	}
 } 
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
这道题是一道典型的费用限制最短路题目,可以使用 Dijkstra 算法或者 SPFA 算法来解决。 具体思路如下: 1. 首先,我们需要读入输入数据。输入数据中包含了道路的数量、起点和终点,以及每条道路的起点、终点、长度和限制费用。 2. 接着,我们需要使用邻接表或邻接矩阵来存储图的信息。对于每条道路,我们可以将其起点和终点作为一个有向边的起点和终点,长度作为边权,限制费用作为边权的上界。 3. 然后,我们可以使用 Dijkstra 算法或 SPFA 算法求解从起点到终点的最短路径。在这个过程中,我们需要记录到每个点的最小费用和最小长度,以及更新每条边的最小费用和最小长度。 4. 最后,我们输出从起点到终点的最短路径长度即可。 需要注意的是,在使用 Dijkstra 算法或 SPFA 算法时,需要对每个点的最小费用和最小长度进行松弛操作。具体来说,当我们从一个点 u 经过一条边 (u,v) 到达另一个点 v 时,如果新的费用和长度比原来的小,则需要更新到达 v 的最小费用和最小长度,并将 v 加入到优先队列(Dijkstra 算法)或队列(SPFA 算法)中。 此外,还需要注意处理边权为 0 或负数的情况,以及处理无法到达终点的情况。 代码实现可以参考以下样例代码: ```c++ #include <cstdio> #include <cstring> #include <queue> #include <vector> using namespace std; const int MAXN = 1005, MAXM = 20005, INF = 0x3f3f3f3f; int n, m, s, t, cnt; int head[MAXN], dis[MAXN], vis[MAXN]; struct Edge { int v, w, c, nxt; } e[MAXM]; void addEdge(int u, int v, int w, int c) { e[++cnt].v = v, e[cnt].w = w, e[cnt].c = c, e[cnt].nxt = head[u], head[u] = cnt; } void dijkstra() { priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> q; memset(dis, 0x3f, sizeof(dis)); memset(vis, 0, sizeof(vis)); dis[s] = 0; q.push(make_pair(0, s)); while (!q.empty()) { int u = q.top().second; q.pop(); if (vis[u]) continue; vis[u] = 1; for (int i = head[u]; i != -1; i = e[i].nxt) { int v = e[i].v, w = e[i].w, c = e[i].c; if (dis[u] + w < dis[v] && c >= dis[u] + w) { dis[v] = dis[u] + w; q.push(make_pair(dis[v], v)); } } } } int main() { memset(head, -1, sizeof(head)); scanf("%d %d %d %d", &n, &m, &s, &t); for (int i = 1; i <= m; i++) { int u, v, w, c; scanf("%d %d %d %d", &u, &v, &w, &c); addEdge(u, v, w, c); addEdge(v, u, w, c); } dijkstra(); if (dis[t] == INF) printf("-1\n"); else printf("%d\n", dis[t]); return 0; } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值