T1】记数问题

试计算在区间1 到n 的所有整数中,数字x(0 ≤ x ≤ 9)共出现了多少次?例如,在1到11 中,即在1、2、3、4、5、6、7、8、9、10、11中,数字1 出现了4 次。

其实这个问题也很经典了。。。

别想很复杂,其实打暴力完全OK

#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<stack>
#include<cstdio>
#include<queue>
#include<map>
#include<vector>
#include<set>
using namespace std;
const int maxn=1010;
const int INF=0x3fffffff;

int n,x;
int main(){
	cin>>n>>x;
	int ans=0;
	for(int i=1;i<=n;i++){
		int temp=i;
		while(temp){
			if(temp%10==x) ans++;
			temp/=10;
		}
	}
	cout<<ans<<endl;
return 0;
}

  

T2】表达式求值

 这种题也是经典题,stack

其实只有加法,和乘法那就很简单好做了,在输入的过程中只需要额外处理乘法,+可以留到最后在统一处理

  

#include <iostream>
#include <cstring>
#include<cstdio>
#include<stack>
#include <algorithm>
using namespace std;
const int maxn=1e4+10;
const int INF=0x3f3f3f3f;
//更简单的写法
stack<int> st; 
int main(){
	int a,b;
	char c;
	cin>>a; //先输入一个数字
	int mod=10000;
	a%=mod;
	st.push(a);
	while(cin>>c>>b){
		if(c=='*'){
			a=st.top();
			st.pop();
			st.push(a*b%mod);
		}
		else st.push(b);
	} 
	a=0;
	while(!st.empty()){
		a+=st.top();
		a%=mod;
		st.pop();
	}
	cout<<a<<endl;
  return 0;
}

  

T3  小朋友的数字

 

 

 这道题涉及到一个细节,取余所导致的结果不同和太大值之间的问题

#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<stack>
#include<cstdio>
#include<queue>
#include<map>
#include<vector>
#include<set>
using namespace std;
const int maxn=1000001;
const int INF=0x3fffffff;
long long res[maxn],d[maxn],dp[maxn];
//d[i]是特征值,res是得分,dp是前i项的和,dp[i]=max(0,dp[i-1])+x
//d[i]=max(d[i-1],dp[i]) res[i]=max(res[i-1],res[i-1]+d[i-1]) 
long long n,p;
//但是注意结果有20分拿不到,因为数据范围,如果在计算过程种可能会超过Long long,所以必须边算边取模
//但是取模就无法比较最大值,所以不能直接用Max,但是从第二个人开始分数是没有下降的,所以再运算过程种如果超过Longlong就可以去模
//因为res[1]是不超过long long的,所以在运算过程中一旦超过long long就说明是最大的是res[n], 

int main(){
	cin>>n>>p;
	int x;
	dp[0]=0;
	for(int i=1;i<=n;i++){
		cin>>x; 
		 dp[i]=max(0LL,dp[i-1])+x;  //0后面要加LL 
		if(i==1) {
			d[i]=dp[i];
		}
		else{
			d[i]=max(d[i-1],dp[i]);
		}
	}
	res[1]=d[1];
	res[2]=d[1]+dp[1];
	bool flag=0; //判断在n>=3的过程中,有没有超过long long
	for(int i=3;i<=n;i++){
		res[i]=max(res[i-1],res[i-1]+d[i-1]);
		if(res[i]>1e9){
			flag=1;
			res[i]=res[i]%p;
		}
	}
	 if(flag) cout<<res[n]%p<<endl;
	 else cout<<max(res[1],res[n])%p<<endl;
return 0;
}

  

T4】车站分级

 

 想不到是考图吧哈哈哈,但是这道题的连线端点要注意,从小的指向大的,是在从经过的车站之间没停靠的车站都是明确小于的,所以可以连线

#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<stack>
#include<cstdio>
#include<queue>
#include<map>
#include<vector>
#include<set>
using namespace std;
const int maxn=1010;
const int INF=0x3fffffff;
//这道题是考图,经过大于等于比当前等级的车站,就能总结出比当前等级小的和大的,让小的指向大的
//再拓扑排序,及查找深度,就能够得出至少深度得多少 
int n,m;
int to[maxn],in[maxn],mapp[maxn][maxn];
int temp[maxn],vis[maxn];
int main(){
	cin>>n>>m;
	int num;
	for(int i=1;i<=m;i++){
		cin>>num;
		int x,t=0,l,r;
		memset(temp,0,sizeof(temp));
		memset(vis,0,sizeof(vis));
		memset(to,0,sizeof(to));
		for(int j=1;j<=num;j++){
			cin>>x;
			if(j==1) l=x;
			if(j==num) r=x;
			temp[j]=x;vis[x]=1;
		}
		for(int z=l;z<=r;z++){
			if(vis[z]==0){
				to[++t]=z;
			}
		}
		//把小的都指向大的
		for(int j=1;j<=t;j++){
			for(int z=1;z<=num;z++) mapp[to[j]][temp[z]]=1;
		} 
	}
	//下面初始化入度 
	for(int i=1;i<=n;i++){
		in[i]=0;
		for(int j=1;j<=n;j++) if(mapp[j][i]) in[i]++;
	}
	int ans=1;
	memset(temp,0,sizeof(temp));
	while(true){
		bool f=0;
		for(int i=1;i<=n;i++){
			temp[i]=in[i];
		}
		for(int i=1;i<=n;i++){
			if(temp[i]==0) {
				for(int j=1;j<=n;j++){
					if(mapp[i][j]){
						mapp[i][j]=0;
						in[j]--;
					}
				}
			}
			else f=1; //如果没有说明还需要继续循环 
		}
	
		if(f==0) break; //如果没有更新了就可以退出 
			ans++;
	}
	cout<<ans<<endl;
return 0;
}

  

 posted on 2020-09-06 22:43  shirlybabyyy  阅读(241)  评论(0编辑  收藏  举报