CSP-J模拟赛day3——解析+答案

小人快跑

思路

按照题意,贪心即可。需要注意的是,这道题目需要开long long。

Code

#include<bits/stdc++.h>
using namespace std;

int main(){
	//freopen("a.in","r",stdin);
	//freopen("a.out","w",stdout);
	long long n,t;
	cin>>n>>t;
	for (int i=1;i<=n;i++){
		int tmp;
		cin>>tmp;
		char a;
		long long b,num=INT_MIN;
		for (int j=1;j<=tmp;j++){
			cin>>a>>b;
			if (a=='+')num=max(num,t+b);
			else if (a=='-')num=max(num,t-b);
			else if (a=='*')num=max(num,t*b);
			else if (a=='%')num=max(num,t%b);
			else num=max(num,t/b);
		}
		t=num;
		if (t<=0){
			cout<<0;
			return 0;
		}
	}
	cout<<t;
	return 0;
}

开根号

思路

按照题意模拟即可。需要注意的是,这道题目需要开long long。

同时,在最后,需要一个gcd函数,得到最简假分数。

Code

#include<bits/stdc++.h>
using namespace std;

int main(){
	long long x,n;
	cin>>x>>n;
	long long tmp=ceil(sqrt(x));
	long long t1,t2=1;
	for (int i=1;i<=n;i++){
		t1=tmp*tmp+t2*t2*x;
		t2=2*tmp*t2;
		tmp=t1;
	}
	long long q=0;
	if (t1>=t2)q=__gcd(t1,t2);
	else q=__gcd(t2,t1);
	if (t2/q==1)cout<<t1/q;
	else cout<<t2/q<<" "<<t1/q;
	return 0;
}

奶茶

思路

考虑结论:对于节点i,其子节点中有t个一定直接或者间接走到叶子节点,这个节点能够走到叶子节点的充分必要条件是 t > a i t>a_i t>ai.

然后就是朴实无华的递推过程了。

Code

#include<bits/stdc++.h>
#define int long long

using namespace std;

int n,m,q;

int a[1000005];

int head[1000005],cnt;

int naicha[1000005];//判断这个点是否有奶茶店 

struct A{
	int to,nxt;
}ed[1000005];

void add(int x,int y){
	ed[++cnt].to=y;
	ed[cnt].nxt=head[x];//更新 head 数组,使得 head[x] 指向最新添加的边的索引 cnt。 
	head[x]=cnt;
}

int chudu[1000005];

int loq[10005];

int dfs(int u){
	if(naicha[u])
		return naicha[u];
	for(int i=head[u];i;i=ed[i].nxt){
		int x=ed[i].to;
		naicha[u]+=(dfs(x)?1:0);//dfs求解 
	}
	naicha[u]-=a[u];//删除拥堵路段 
	return naicha[u]=(naicha[u]>=1?1:0);//判断是否还有剩余 
}

signed main(){
	cin>>n>>q;
	for(int i=1;i<=n;++i){
		cin>>a[i];//拥堵方式 
	}
	for(int i=2;i<=n;++i){
		int x,y;
		cin>>x>>y;
		add(x,y);
		chudu[x]++;//出度加1 
	}
	for(int i=1;i<=n;++i){
		if(chudu[i]==0)naicha[i]=1;//判断当前这个点是否有奶茶店 
	}
	for(int i=1;i<=q;++i){
		cin>>loq[i];
	}
	dfs(1);
	for(int i=1;i<=q;++i){
		if(naicha[loq[i]]==1)cout<<"YES"<<endl;//根据有没有奶茶店来判断 
		else cout<<"NO"<<endl;
	}
	return 0;
}

密码锁

思路

数据点1-2满足, n = 1 n = 1 n=1

送分,简单判断差的绝对值就好了。

数据点3-4满足, n = 2 n = 2 n=2

尝试加减1,10,11来得到正确答案,3重循环能过

数据点5-6满足, n = 4 n = 4 n=4

尝试加减1,10,100,1000,11,110,1100来得到正确答案,7重循环能过

数据点7-8满足, n = 6 n = 6 n=6

开1e6数组记录,类似最短路的算法或者记忆化搜索能过,但是对常数要求比较大

数据点9-12满足, 1 ≤ n ≤ 1000 1 \le n \le 1000 1n1000

允许一些 n 2 n^2 n2的DP通过,比如一些区间DP。做法有很多,但是会比较复杂。

数据点13-20满足, 1 ≤ n ≤ 1 × 1 0 5 1 \le n \le 1\times 10^5 1n1×105

考虑动态规划:dp[i][j]表示,从初始状态,到达“当前从左往右前 i-1 位都已经恢复,并且第 i 位目前是为 j ”这一状态的最小次数 (要求,状态转移时只拨第 i 位与 i-1 位,或者只拨动第 i 位)

时间复杂度是O(n)的,带有100的常数。

Code

#include<bits/stdc++.h>
#define int long long

using namespace std;

const int N=1000000+5;

int n;
char s[N];
int a[N], b[N];
int dp[N][10];

signed main(){
	cin>>n;
	scanf("%s",s+1);
	for(int i=1;i<=n;++i)
		a[i]=s[i]-'0';
	scanf("%s",s+1);
	for(int i=1;i<=n;++i)
		b[i]=s[i]-'0';
	memset(dp,0x3f,sizeof(dp));
	for(int i=0;i<=9;++i)
		dp[1][i]=min((i-b[1]+10)%10,(b[1]-i+10)%10);
	for(int i=2;i<=n;++i)
		for(int j=0;j<=9;++j)
			for(int k=0,c,t;k<=9;++k){
				c=(a[i-1]-k+10)%10,t=(b[i]+c)%10;
				dp[i][j]=min(dp[i][j],dp[i-1][k]+c+min((j-t+10)%10,(t-j+10)%10));
				c=(k-a[i-1]+10)%10,t=(b[i]-c+10)%10;
				dp[i][j]=min(dp[i][j],dp[i-1][k]+c+min((j-t+10)%10,(t-j+10)%10));
			}
	printf("%lld",dp[n][a[n]]);
	return 0;
}

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值