台州学院第十六届大学生程序设计竞赛题解

动态规划之01背包问题及leetcode实例 01背包问题 这篇文章讲的很清楚,我这里就不赘述了。 https://www.cnblogs.com/Christal-R/p/Dynamic_programming.html leetcode problem 416 描述 Given a non-empty array containing only positive integers, find if the array 阅读详情

A题

'c’本就弱小(tzcoder8390)

思路

水题

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

int main(){
	double a,b,c;
	cin>>a>>b>>c;
	if(c+a>b&&c+b>a) cout<<"Yes"<<endl;
	else cout<<"No"<<endl;
	return 0;
}

B题

XOR!(tzcoder8391)

思路

模拟题,难点在于怎么处理中间的符号以及切割出整数值

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

int main(){
	int t;
	cin>>t;
	while(t--){
		string s;
		cin>>s;
		int cas;//中间的运算符是什么 
		int num_left=0,num_right=0;//num_left是式子左侧的值,num_right是式子右侧的值
		int now=0;//当前切割的数字 
		for(int i=0;i<s.size();i++){
			if(s[i]=='^'){
				num_left^=now;
				now=0;
			}
			else if(s[i]=='+'){
				num_right+=now;
				now=0;
			}
			else if(s[i]>='0'&&s[i]<='9'){
				now=now*10+s[i]-'0';
			}
			else{//此时必定是中间的运算符
				num_left^=now;//注意处理最后一个整数 
				now=0; 
				//注意用if写的话,情况3要写在情况0前,情况4要写在情况1前面 
				if(s[i]=='<'&&s[i+1]=='=') cas=3,i++;
				else if(s[i]=='>'&&s[i+1]=='=') cas=4,i++;
				else if(s[i]=='!') cas=5,i++;//注意这里下标多+1,否则会和后面的=情况重复 
				else if(s[i]=='<') cas=0;
				else if(s[i]=='>') cas=1;
				else if(s[i]=='=') cas=2;
			}
		}
		num_right+=now;//右侧的最后一个整数不要忘记处理
		int flag;
		switch(cas){
			case 0:flag=num_left<num_right;break; 
			case 1:flag=num_left>num_right;break; 
			case 2:flag=num_left==num_right;break; 
			case 3:flag=num_left<=num_right;break; 
			case 4:flag=num_left>=num_right;break; 
			case 5:flag=num_left!=num_right;break; 
		} 
		if(flag) cout<<"Yes"<<endl;
		else cout<<"No"<<endl;
	}
}

C题

乐乐的强迫症(tzcoder8392)

思路

010101背包模型
从aaa到bbb,其实就是能不能凑出b−ab-ab−a的分数。
把分值看做容量,这就是一道010101背包的经典模型。
注意特判a>ba>ba>b的情况

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

int dp[40007];//dp[i]代表凑出分数i的最少题目数量 

int main(){
	int n,a,b;
	cin>>n>>a>>b;
	if(a>b){
		cout<<-1<<endl;
		return 0;
	}
	dp[0]=0;//初始情况,0分是可以凑出来的 
	int lim=b-a;
	for(int i=1;i<=lim;i++) dp[i]=1e9;
	while(n--){
		int x;
		cin>>x;
		for(int i=lim;i>=x;i--){
			dp[i]=min(dp[i],dp[i-x]+1);
		}
	}
	if(dp[lim]==1e9) cout<<-1<<endl;
	else cout<<dp[lim]<<endl;
}

D题

maomeng的数学魔鬼训练(tzcoder8393)

思路

贪心
从直觉上,我们肯定要把耗时最长的书和耗时最少的游戏安排在同一天
那么如果我们把书按照耗时从大到小排序,把游戏按照耗时从小到大排序,是否这样的顺序就一定是最优的呢?

答案是必然的,证明如下
比如我们尝试对第iii多耗时的书(定义为x[i]x[i]x[i])和第iii少耗时的游戏(定义为y[i]y[i]y[i])安排在同一天
如果x[i]+y[i]>24x[i]+y[i]>24x[i]+y[i]>24,则无法安排
那么我们尝试,肯定要把x[i]x[i]x[i]或者y[i]y[i]y[i]中的一个尝试缩小
如果我们尝试缩小y[i]y[i]y[i],也就是说要取一个j<ij<ij<i,尝试用y[j]y[j]y[j]替代y[i]y[i]y[i]
那么即使我们可以使得x[i]+y[j]<=24x[i]+y[j]<=24x[i]+y[j]<=24成立,但是造成的影响x[j]+y[i]x[j]+y[i]x[j]+y[i]必定是>24>24>24的,因为x[j]>x[i]x[j]>x[i]x[j]>x[i]

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

int main(){
	int n;
	cin>>n;
	int a[1007],b[1007];
	for(int i=0;i<n;i++) cin>>a[i];
	for(int i=0;i<n;i++) cin>>b[i];
	sort(a,a+n);
	sort(b,b+n);
	for(int i=0;i<n;i++){
		if(a[i]+b[n-i-1]>24){
			cout<<"NO"<<endl;
			return 0; 
		}
	}
	cout<<"YES"<<endl;
}

E题

##回文自动机(tzcoder8394)

思路

dp+dp+dp+矩阵快速幂加速
需要借助哈希计算
见注释

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn=2e5+7;
const int mod=1000000007;
string s;
long long hash_pre[maxn*2],hash_suf[maxn*2];
long long ans[2];//ans[0]代表回文的情况数,ans[1]代表不回文的情况数 
long long mat[2][2];//关系转移矩阵 
long long temp_base=1;//截取下来的一半字符串最高位+1对应的权值 
int cnt=0;

void mul_mat(long long a[2][2],long long b[2][2]){
	//计算矩阵a*矩阵b
	long long c[2][2];
	memset(c,0,sizeof(c));
	for(int i=0;i<2;i++){
		for(int j=0;j<2;j++){
			for(int k=0;k<2;k++){
				c[i][j]=(a[i][k]*b[k][j]%mod+c[i][j])%mod;
			}
		}
	} 
	for(int i=0;i<2;i++){
		for(int j=0;j<2;j++){
			a[i][j]=c[i][j];
		}
	}
}

void qpow(long long a[2][2],long long p){
	long long ans[2][2];
	ans[0][0]=ans[1][1]=1;
	ans[0][1]=ans[1][0]=0;
	while(p){
		if(p&1) mul_mat(ans,a);
		mul_mat(a,a);
		p>>=1;
	}
	for(int i=0;i<2;i++){
		for(int j=0;j<2;j++){
			a[i][j]=ans[i][j];
		}
	}
}

int main(){
	string s;
	long long k;
	cin>>s>>k;
	int len=s.size();
	s=s+s;
	for(int i=0;i<len*2;i++) hash_pre[i+1]=(hash_pre[i]*10%mod+s[i]-'a')%mod;
	for(int i=len*2-1;i>=0;i--) hash_suf[i+1]=(hash_suf[i+2]*10%mod+s[i]-'a')%mod;
	for(int i=0;i<len/2;i++) temp_base=temp_base*10%mod;
//	for(int i=1;i<=len*2;i++){
//		cout<<hash_pre[i]<<' '<<hash_suf[i]<<' '<<i<<endl; 
//	}
	for(int i=1;i<=len;i++){
		//以第i个字符作为字符串开头的情况
		long long hash1,hash2;
		if(len&1){
			//奇数情况下,第一段是[i,i+len/2-1],第二段是[i+len/2+1,i+len-1] 
			hash1=(hash_pre[i+len/2-1]-hash_pre[i-1]*temp_base%mod+mod)%mod;
			hash2=(hash_suf[i+len/2+1]-hash_suf[i+len]*temp_base%mod+mod)%mod;
			//cout<<hash1<<' '<<hash2<<' '<<i<<'!'<<endl;
		} 
		else{
			//偶数情况下,第一段是[i,i+len/2-1],第二段是[i+len/2,i+len-1] 
			hash1=(hash_pre[i+len/2-1]-hash_pre[i-1]*temp_base%mod+mod)%mod;
			hash2=(hash_suf[i+len/2]-hash_suf[i+len]*temp_base%mod+mod)%mod;
		}
		if(hash1==hash2){
			cnt++;
		}
		if(i==1){
			if(hash1==hash2) ans[0]=1;
			else ans[1]=1;
		}
	}
	mat[0][0]=cnt-1;//从回文转移到回文有cnt-1种 
	mat[1][0]=cnt;//从非回文转移到回文有cnt种 
	mat[0][1]=len-cnt;//从回文转移到非回文有len-cnt种 
	mat[1][1]=len-cnt-1;//从非回文转移到非回文有len-cnt-1种 
//	for(int i=0;i<2;i++){
//		for(int j=0;j<2;j++){
//			cout<<mat[i][j]<<' ';
//		}
//		cout<<endl;
//	}
	qpow(mat,k);
//	for(int i=0;i<2;i++){
//		for(int j=0;j<2;j++){
//			cout<<mat[i][j]<<' ';
//		}
//		cout<<endl;
//	}
	//最后计算ans矩阵乘以mat矩阵即可 
	//ans[0]就是答案 
	cout<<(ans[0]*mat[0][0]%mod+ans[1]*mat[1][0]%mod)%mod<<endl;
} 

F题

狭路相逢勇者胜!(tzcoder8395)

思路

思维结论,无算法
需要先能观察推导出,当前这一轮的第i位选手,如果他获胜晋级,那么他在下一轮会是第i/2i/2i/2位选手。

在此基础上,再想到什么时候两个人会相遇,即两个人的序号差值为111,并且小的那名选手的序号是偶数。

因此不断循环模拟晋级过程即可,一直到两个人相遇。复杂度log(n)log(n)log(n)

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

int main(){
    int n,a,b;
    cin>>n>>a>>b;
    if(a>b) swap(a,b);//注意题目没说a>b,不交换会导致下面的循环死循环
    int ans=1;
    while(a%2||b!=a+1){
        a>>=1;
        b>>=1;
        ans++;
    }
    cout<<ans<<endl;
}

G题

“TZOJ”(tzcoder8396)

思路

此题可以n2n^2n2复杂度枚举每个点,作为我们选择的正方形区域的最左上角。
然后如果直接nnn复杂度枚举正方形区域的边长,借助二维前缀和O(1)O(1)O(1)计算区域内的T,Z,O,J的个数。
这种写法的复杂度是n3n^3n3,会超时。

容易注意到,对于左上角固定某个位置的情况下,边长越长,越可能满足包含T,Z,O,J的这个条件,也就是存在一个值x,当边长>=x时,正方形区域都满足要求,也就是满足二分性。
因此我们可以二分正方形的边长,将复杂度降低到O(n2∗logn)O(n^2*logn)O(n2∗logn)

不过这里还可以继续优化
我们以[i][j][i][j][i][j]作为正方形的左上角时,其实对于所有的i−j=k,ki-j=k,ki−j=k,k是一个常数,也就是说对于从左上角斜向右下角的斜454545度线上的所有矩形,我们是可以放在一起讨论的。
如果说从这个“线性”角度思考,很容易发现是满足双指针移动方向的单调性。
即以[i][j][i][j][i][j]作为左上角,[toi][toj][toi][toj][toi][toj]作为正方形区域刚好包含T,Z,O,J时的右下角
对于i−j=k,ki-j=k,ki−j=k,k是一个常数时,明显iii和jjj越大,toitoitoi和tojtojtoj也越大。

因此对于每个斜线情况,我们可以采用双指针的策略,将整体复杂度降低到O(n2)O(n^2)O(n2)
注意此时我们枚举矩阵左上角位置的顺序,也应该变成斜454545度方向

同时双指针的写法由于每次长度只扩展111,因此可以只使用一维前缀和,当然使用二维前缀和代码会更简洁和容易理解。
下方代码写的是一维前缀和。

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

int n,m;
char field[1007][1007];

struct Node{
    int T,Z,O,J;
}sum[2][1007][1007];
//sum[0]是横向的前缀和
//sum[1]是竖向的前缀和

int main(){
    memset(sum,0,sizeof(sum));
    cin>>n>>m;
    for(int i=0;i<n;i++) cin>>field[i];
    for(int i=0;i<n;i++){
        for(int j=0;j<m;j++){
            if(field[i][j]=='T') sum[0][i+1][j+1].T=sum[1][i+1][j+1].T=1;
            else if(field[i][j]=='Z') sum[0][i+1][j+1].Z=sum[1][i+1][j+1].Z=1;
            else if(field[i][j]=='O') sum[0][i+1][j+1].O=sum[1][i+1][j+1].O=1;
            else if(field[i][j]=='J') sum[0][i+1][j+1].J=sum[1][i+1][j+1].J=1;
        }
    }
    //做横向前缀和
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            sum[0][i][j].T+=sum[0][i][j-1].T;
            sum[0][i][j].Z+=sum[0][i][j-1].Z;
            sum[0][i][j].O+=sum[0][i][j-1].O;
            sum[0][i][j].J+=sum[0][i][j-1].J;
        }
    }
    //做竖向前缀和
    for(int j=1;j<=m;j++){
        for(int i=1;i<=n;i++){
            sum[1][i][j].T+=sum[1][i-1][j].T;
            sum[1][i][j].Z+=sum[1][i-1][j].Z;
            sum[1][i][j].O+=sum[1][i-1][j].O;
            sum[1][i][j].J+=sum[1][i-1][j].J;
        }
    }
    int ans=0;
    //以field[nowi][nowj]作为我们正方形区域的左上角,共n^2种情况,借助双指针思想,整体复杂度仍为O(n^2)
    //先计算整个矩形右上角一侧的点作为正方形区域的左上角的情况
    for(int j=1;j<=m;j++){
        int nowi=1,nowj=j;//field[nowi][nowj]作为正方形区域的左上角
        int to_i=nowi,to_j=nowj;//field[to_i][to_j]作为正方形区域的右下角
        int T=sum[0][nowi][nowj].T-sum[0][nowi][nowj-1].T;
        int Z=sum[0][nowi][nowj].Z-sum[0][nowi][nowj-1].Z;
        int O=sum[0][nowi][nowj].O-sum[0][nowi][nowj-1].O;
        int J=sum[0][nowi][nowj].J-sum[0][nowi][nowj-1].J;
        //T,Z,O,J统计当前正方形区域中对应字符的个数
        while(nowi<=n&&nowj<=m){         
            while(1){
                if(T&&Z&&O&&J) break;//当前边长足够长,包含了四种字符
                if(to_i==n||to_j==m) break;//右下角已经无法再往右下方向拓展
                //右侧增加一列,对应下标field[nowi][to_j+1]到field[to_i+1][to_j+1]
                T+=sum[1][to_i+1][to_j+1].T-sum[1][nowi-1][to_j+1].T;
                Z+=sum[1][to_i+1][to_j+1].Z-sum[1][nowi-1][to_j+1].Z;
                O+=sum[1][to_i+1][to_j+1].O-sum[1][nowi-1][to_j+1].O;
                J+=sum[1][to_i+1][to_j+1].J-sum[1][nowi-1][to_j+1].J;
                //底部增加一行,对应下标field[to_i+1][nowj]到field[to_i+1][to_j]//这里没有+1,右下角那个点别算重复了
                T+=sum[0][to_i+1][to_j].T-sum[0][to_i+1][nowj-1].T;
                Z+=sum[0][to_i+1][to_j].Z-sum[0][to_i+1][nowj-1].Z;
                O+=sum[0][to_i+1][to_j].O-sum[0][to_i+1][nowj-1].O;
                J+=sum[0][to_i+1][to_j].J-sum[0][to_i+1][nowj-1].J;
                to_i++;
                to_j++;
                //右下角往右下尝试拓展长度1
            }
            if(T&&Z&&O&&J) ans+=min(n-to_i+1,m-to_j+1);//比当前右下角更右下的位置都满足答案
            //左上角尝试往右下挪动距离1的位置
            //上侧减少一行,对应下标field[nowi][nowj]到field[nowi][to_j]
            T-=sum[0][nowi][to_j].T-sum[0][nowi][nowj-1].T;
            Z-=sum[0][nowi][to_j].Z-sum[0][nowi][nowj-1].Z;
            O-=sum[0][nowi][to_j].O-sum[0][nowi][nowj-1].O;
            J-=sum[0][nowi][to_j].J-sum[0][nowi][nowj-1].J;
            //左侧减少一列,对应下标field[i+1][nowj]到field[to_i][nowj]   //这里也一样别把左上角的点多算了一次
            T-=sum[1][to_i][nowj].T-sum[1][nowi][nowj].T;
            Z-=sum[1][to_i][nowj].Z-sum[1][nowi][nowj].Z;
            O-=sum[1][to_i][nowj].O-sum[1][nowi][nowj].O;
            J-=sum[1][to_i][nowj].J-sum[1][nowi][nowj].J;
            nowi++;
            nowj++;
        }
    }
    //再计算整个矩形左下角一侧的点作为正方形区域的左上角的情况
    for(int i=2;i<=n;i++){
        int nowi=i,nowj=1;
        int to_i=nowi,to_j=nowj;//field[to_i][to_j]作为正方形区域的右下角
        int T=sum[0][nowi][nowj].T-sum[0][nowi][nowj-1].T;
        int Z=sum[0][nowi][nowj].Z-sum[0][nowi][nowj-1].Z;
        int O=sum[0][nowi][nowj].O-sum[0][nowi][nowj-1].O;
        int J=sum[0][nowi][nowj].J-sum[0][nowi][nowj-1].J;
        //T,Z,O,J统计当前正方形区域中对应字符的个数
        while(nowi<=n&&nowj<=m){         
            while(1){
                if(T&&Z&&O&&J) break;//当前边长足够长,包含了四种字符
                if(to_i==n||to_j==m) break;//右下角已经无法再往右下方向拓展
                //右侧增加一列,对应下标field[nowi][to_j+1]到field[to_i+1][to_j+1]
                T+=sum[1][to_i+1][to_j+1].T-sum[1][nowi-1][to_j+1].T;
                Z+=sum[1][to_i+1][to_j+1].Z-sum[1][nowi-1][to_j+1].Z;
                O+=sum[1][to_i+1][to_j+1].O-sum[1][nowi-1][to_j+1].O;
                J+=sum[1][to_i+1][to_j+1].J-sum[1][nowi-1][to_j+1].J;
                //底部增加一行,对应下标field[to_i+1][nowj]到field[to_i+1][to_j]//这里没有+1,右下角那个点别算重复了
                T+=sum[0][to_i+1][to_j].T-sum[0][to_i+1][nowj-1].T;
                Z+=sum[0][to_i+1][to_j].Z-sum[0][to_i+1][nowj-1].Z;
                O+=sum[0][to_i+1][to_j].O-sum[0][to_i+1][nowj-1].O;
                J+=sum[0][to_i+1][to_j].J-sum[0][to_i+1][nowj-1].J;
                to_i++;
                to_j++;
                //右下角往右下尝试拓展长度1
            }
            if(T&&Z&&O&&J) ans+=min(n-to_i+1,m-to_j+1);//比当前右下角更右下的位置都满足答案
            //左上角尝试往右下挪动距离1的位置
            //上侧减少一行,对应下标field[nowi][j]到field[nowi][to_j]
            T-=sum[0][nowi][to_j].T-sum[0][nowi][nowj-1].T;
            Z-=sum[0][nowi][to_j].Z-sum[0][nowi][nowj-1].Z;
            O-=sum[0][nowi][to_j].O-sum[0][nowi][nowj-1].O;
            J-=sum[0][nowi][to_j].J-sum[0][nowi][nowj-1].J;
            //左侧减少一列,对应下标field[nowi+1][nowj]到field[to_i][nowj]   //这里也一样别把左上角的点多算了一次
            T-=sum[1][to_i][nowj].T-sum[1][nowi][nowj].T;
            Z-=sum[1][to_i][nowj].Z-sum[1][nowi][nowj].Z;
            O-=sum[1][to_i][nowj].O-sum[1][nowi][nowj].O;
            J-=sum[1][to_i][nowj].J-sum[1][nowi][nowj].J;
            nowi++;
            nowj++;
        }
    }
    cout<<ans<<endl;
}

H题

佳加简减(tzcoder8397)

思路

看起来吓人,其实很简单
非严格上升子序列的长度+++非严格下降子序列的长度尽可能大
非严格上升子序列的最大长度是nnn
非严格下降子序列的最大长度是nnn
能不能两个同时取nnn?
可以,整个数列里的数都相等就可以。

那么这道题就变成了把整个数组里的所有数变成相同的同一个数,最少的操作次数

这就是一个经典的中位数的题目了

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+7;

int num[maxn];

int main(){
	int n;
	scanf("%d",&n); 
	for(int i=0;i<n;i++) scanf("%d",&num[i]);
	sort(num,num+n);
	long long ans=0;
	int base=num[n/2];
	for(int i=0;i<n;i++) ans+=abs(num[i]-base);
	printf("%lld\n",ans); 
}

I题

Auuuu的水题(tzcoder8398)

思路

二维平面上的多源bfs
直接把所有初始为水源的点压到队列里,统计每个非水源点周围水源点的个数。
每次从队列里弹出一个水源位置,更新周围非水源点记录的水源点个数信息,一旦有222个以上水源就把这个位置修改为水源,同时压入队列中等待更新周边位置。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn=507;

int n,m;
char field[maxn][maxn];
int cnt[maxn][maxn];//cnt[i][j]代表(i,j)这个位置周围有几个点是水源
struct Node{
    int x,y;
};
queue<Node>Q;

int dir[4][2]={//对应朝着四个方向走
    1,0,
    -1,0,
    0,1,
    0,-1
};

int main(){
    cin>>n>>m;
    for(int i=0;i<n;i++) cin>>field[i];
    for(int i=0;i<n;i++){
        for(int j=0;j<m;j++){
            if(field[i][j]=='*') Q.push({i,j});
        }
    }
    while(Q.size()){
        Node now=Q.front();
        Q.pop();
        for(int i=0;i<4;i++){
            int nextx=now.x+dir[i][0];
            int nexty=now.y+dir[i][1];
            if(nextx>=0&&nextx<n&&nexty>=0&&nexty<m){//保证在地图内
                if(field[nextx][nexty]=='.'){
                    cnt[nextx][nexty]++;//周围水源点个数+1
                    if(cnt[nextx][nexty]==2){//超过两个点
                        Q.push({nextx,nexty});
                        field[nextx][nexty]='*';//当前位置变为水源点
                    }
                }
            }
        }
    }
    for(int i=0;i<n;i++) cout<<field[i]<<endl;
}

J题

Auuuu的粥游账号(tzcoder8399)

思路

dfs暴力枚举所有情况的经典题,同时兼备字典序
必须学会
后期骗分必备写法

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

int n;
bool flag[27];//记录每个数有没有被使用过 
struct Node{
	int num[12];
};
vector<Node>out;
Node temp;

void dfs(int deep,int x){//x代表前面用过的数最大是多少 
	if(deep==12){
		out.push_back(temp);
		return;
	}
	//deep代表当前暴力枚举第deep个数放什么
	for(int j=x+1;j<=n;j++){
		//注意从小到大枚举,这样就可以保证字典序
		if(flag[j]) continue;//被用过了就跳过
		flag[j]=1;//标记为被使用过
		temp.num[deep]=j;
		dfs(deep+1,j);
		flag[j]=0;//记得还原 
	} 
}

int main(){
	cin>>n;
	dfs(0,0);
	cout<<out.size()<<endl;
	for(int i=0;i<out.size();i++){
		for(int j=0;j<12;j++){
			if(j) cout<<' ';
			cout<<out[i].num[j];
		}
		cout<<endl;
	}
}

K题

上课不要讲话 (tzcoder8400)

思路

可以把第一个人能坐的所有位置的周围位置都打上标记
然后监测第二个人能不能坐在打上标记的位置上即可
注意不要忘记考虑两个人初始位置也是一种选择

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn=107;

int n,m,a,b;
bool flag[maxn][maxn];
//flag[i][j]代表第i行第j列这个位置能不能与Richadal相邻

int main(){
    cin>>n>>m>>a>>b;
    flag[0][1]=flag[1][0]=flag[1][1]=1;//别忘了初始位置
    while(a--){
        int temp;
        cin>>temp;
        //temp对应在第(temp-1)/m行,第(temp-1)%m列
        int nowr=(temp-1)/m,nowc=(temp-1)%m;
        for(int i=-1;i<=1;i++){
            for(int j=-1;j<=1;j++){//枚举周围8个格子
                if(i==0&&j==0) continue;

                if(nowr+i>=0&&nowr+i<n&&nowc+j>=0&&nowc+j<m) flag[nowr+i][nowc+j]=1;
            }
        }
    }
    while(b--){
        int temp;
        cin>>temp;
        int nowr=(temp-1)/m,nowc=(temp-1)%m;
        if(flag[nowr][nowc]){
            cout<<"Yes"<<endl;
            return 0;
        }
    }
    //这里也不要忘记初始位置
    if(flag[n-1][m-1]){
        cout<<"Yes"<<endl;
        return 0;
    }
    cout<<"No"<<endl;
}

L题

Richadal和他的采矿车 (tzcoder8401)

思路

模拟
多关键字结构体排序
有一个坑点是时间可能会爆int,当目标矿总量10910^9109,而每次只能运111矿石时,所需搬运次数是10910^9109,再乘以每次来回所需时间会超过int。
要学会分析数据范围,不要简单直接#define int long long
long long的计算常数大于int ,并且带来更多内存消耗,以及容易没有分析数据范围的习惯,爆long long的情况可能会反应不过来。

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e3+7;

int n;
int x[maxn],y[maxn],z[maxn],s[maxn];
struct Node{
    long long time;//完成采矿需要的时间
    int tag;//编号
    int cnt;//需要进行的往返次数
}node[maxn];

bool cmp1(Node a,Node b){//采矿快的在前
    if(a.time==b.time) return a.tag<b.tag;
    return a.time<b.time;
}

bool cmp2(Node a,Node b){//轮数少的在前
    if(a.cnt==b.cnt) return a.tag<b.tag;
    return a.cnt<b.cnt;
}

int main(){
    int t;
    cin>>t;
    while(t--){
        cin>>n;
        for(int i=0;i<n/2;i++) cin>>x[i]>>y[i]>>z[i]>>s[i];
        for(int i=n/2;i<n;i++) cin>>x[i]>>y[i]>>s[i];
        int target,k;
        cin>>target>>k;
        for(int i=0;i<n/2;i++){
            node[i].tag=i+1;
            node[i].cnt=(target-1)/s[i]+1;
            node[i].time=node[i].cnt*(long long)(x[i]+y[i]+z[i]);
        }
        for(int i=n/2;i<n;i++){
            node[i].tag=i+1;
            node[i].cnt=(target-1)/s[i]+1;
            node[i].time=node[i].cnt*(long long)(x[i]+y[i]);
        }
        int tempcnt=node[k-1].cnt;//排序后编号k的矿车位置可能改变
        //提前记录下第二个输出
        sort(node,node+n,cmp1);
        cout<<node[k-1].tag<<' '<<node[k-1].cnt<<endl;
        cout<<k<<' '<<tempcnt<<endl;
        sort(node,node+n,cmp2);
        cout<<node[k-1].tag<<' '<<node[k-1].cnt<<endl;
    }
}

M题

yuyu与baby斗地主 (tzcoder8402)

思路

模拟
分类讨论
这里用一个change函数,把牌面转换用具体的数值来表示,数值越大牌面越大

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e3+7;

int n,m;
int cnt1[17],cnt2[17];//统计两个人每种牌有几张

int change(string s){
    if(s.size()>1) return 10;
    if(s[0]>='3'&&s[0]<='9') return s[0]-'0';
    if(s[0]=='J') return 11;
    if(s[0]=='Q') return 12;
    if(s[0]=='K') return 13;
    if(s[0]=='A') return 14;
    if(s[0]=='2') return 15;
    return 16;//剩下的只有大小王
}

int main(){
    cin>>n>>m;
    while(n--){
        string s;
        cin>>s;
        cnt1[change(s)]++;
    }
    while(m--){
        string s;
        cin>>s;
        cnt2[change(s)]++;
    }
    vector<int>S1,S2;//保存两个人的炸弹
    if(cnt1[16]==2) S1.push_back(16);
    for(int i=15;i>=3;i--)
        if(cnt1[i]==4) S1.push_back(i);
    if(cnt2[16]==2) S2.push_back(16);
    for(int i=15;i>=3;i--)
        if(cnt2[i]==4) S2.push_back(i);
    if(S1.size()>S2.size()) cout<<"yuyu"<<endl;
    else if(S1.size()<S2.size()) cout<<"baby"<<endl;
    else{
        if(S1.size()==0){//两个热都没有炸弹,平局
            cout<<"draw"<<endl;
            return 0;
        }
        int flag=0;//代表yuyu比拼炸弹赢baby的次数
        for(int i=0;i<S1.size();i++){
            flag+=S1[i]>S2[i]?1:-1;
        }
        if(flag>0) cout<<"yuyu"<<endl;
        else if(flag<0) cout<<"baby"<<endl;
        else{
            if(S1[0]>S2[0]) cout<<"yuyu"<<endl;
            else cout<<"baby"<<endl;
        }
    }
}
即插即用!5分钟为你的SNN模型添加频谱注意力(DCT-SA模块实战) 本文介绍了如何为脉冲神经网络(SNN)快速集成即插即用的DCT-SA频谱注意力模块。该模块利用离散余弦变换(DCT)在频率域自适应加权特征,能有效提升模型对纹理、边缘的感知能力,并在CIFAR10-DVS等数据集上实现分类精度提升与脉冲发放率下降。文章以SpikingJelly框架和ResNet19为例,提供了详细的代码实现、集成步骤及参数调优实战指南。 阅读详情

相关推荐

别再一个个BAPI调了!用CVI_EI_INBOUND_MAIN一次性搞定SAP BP主数据(附完整ABAP代码)

本文详细介绍了如何使用SAP标准函数CVI_EI_INBOUND_MAIN高效维护业务伙伴(BP)主数据,替代传统的多BAPI调用方式。通过完整ABAP代码示例,展示了如何一站式处理供应商、客户、公司代码等所有视图的创建与更新,提升数据一致性和开发效率。

weixin_29204205的博客 291

TZC Python 基础编程 131-140题

133、6438-与指定数字相同的数的个数。136、6836-新年大合唱比赛得分。138、6860-求小数的某一位。139、6844-设备价格问题。132、5222-奇偶分家。134、1459-求最大值。135、7180-求最小值。140、6824-数麦粒。137、6732-阶乘。

493

MobaXterm破解14个会话限制的保姆级教程(附Python环境配置指南)

本文提供了MobaXterm破解14个会话限制的详细教程,并深入讲解了如何配置稳定的Python环境以支持相关脚本运行。通过理解软件授权机制、安全实践步骤以及许可文件的应用,帮助用户解除会话数量限制,实现高效的远程服务器管理与自动化运维。

weixin_29211309的博客 1641

TZC 高中信息技术(Python)必修题单————题解

python

4459

手把手带你死磕ORBSLAM3源代码(一)目录详解

ORB-SLAM3是一种基于特征点的稀疏实时单目SLAM(Simultaneous Localization and Mapping)系统。它是ORB-SLAM系列模型的第三代版本,用于在无人机、机器人和增强现实等领域中进行实时定位和建图。ORB-SLAM3使用了一种特征点提取和描述算法,称为ORB(Oriented FAST and Rotated BRIEF)。该算法能够提取图像中的稳定特征,并将其用于地图建立和相机定位。

anananajiushiwo的博客 2299

蓝凌EIS智慧协同平台frm_form_upload.aspx接口存在任意文件上传漏洞

蓝凌EIS智慧协同平台frm_form_upload.aspx接口存在任意文件上传漏洞

nnn2188185的博客 357

TZOJ练习 - 1471: Wall

板子题背板子ing

weixin_73623214的博客 671

企业级 Token 中转架构设计:高并发、多模型、费用监控一次搞定

摘要:本文针对企业级AI开发中的多模型接口混乱、高并发稳定性差及Token费用失控等痛点,提出一套2026年企业级Token中转架构解决方案。该方案采用五层分层设计(接入层、网关层、调度层、服务层、存储层),实现多模型统一接口、智能路由、高并发限流容错及精细化成本监控。核心功能包括:异构模型标准化接入、动态路由策略(场景/成本/负载/容灾)、多级限流熔断机制、全链路Token计费与安全防封体系(指纹清洗、IP池隔离)。通过分层解耦与模块化设计,企业可降低50%成本、提升99%稳定性,并避免封号风险。文章还提

远程部署调试 运行安装 项目调试 二次开发 项目技术新 持续迭代 部分源码免费分享 146

LeetCode答案大全题(java版)

思路:查找时, 建立索引(Hash查找) 或进行排序(二分查找)。本题缓存可在找的过程中建立索引,故一个循环可以求出解(总是使用未 使用元素查找使用元素,可以保证每一对都被检索到)。 Indexing/ordering is the first step to search questions. 2. Add Two Numbers 思路:数字进位问题,该位有效值为值%10,进位值为值/10。可以使用一个变量记录进位值 ...

weixin_346127357的博客 677

19. SAP UI5 应用开发教程之十九 - SAP UI5 数据类型和复杂的数据绑定

通过本教程前面的步骤SAP UI5 初学者教程之十七 - 聚合绑定在 UI5 复合控件中的使用的介绍,我们已经学会了如何在 SAP UI5 里显示列表,如下图所示: 本步骤我们给该列表添加更多的业务数据,比如每张发票的金额。 按照本文的步骤完成的 SAP UI5 应用,列表如下图所示: 可以看到,同前一个步骤相比,现在 Invoices 表格里,每张发票的金额和货币单位已经显示出来了。 为了实现这个效果,本步骤的源代码位于我的 Github 这个文件夹下面: https://github.com/wan

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 3692

C#实现网络寻路(附完整源码)

C#实现网络寻路(附完整源码)

希望我的博客,能帮上你解决学习中工作中所遇到的问题 420

TZC Python编程入门教程 ————题解

python

3324

Carla中如何渲染opendrive车道线和车道标识(全网独家,附代码)

carla是可以单独加载opendrive并渲染路面的,但是无法把车道线渲染出来,这是一个大坑,因为没有车道线就无法给感知输入。楼主已经实现,直接渲染车道线或者带PBR贴图的车道标识。实现起来非常简单,但必须对carla源码以及ue的开发足够了解。在carla源码中有一个很重要的类opendrivegenerator,它是关于opendrive渲染的全部方法,但是你是找不到它实例化的地方的,因为它被定义在蓝图关卡中。网上包括carla官方关于carla源码的分析少之又少,楼主将自己的经验写出来供大家参考。

u013998156的博客 1090

LeetCode题解(python)-1002. 查找常用字符

LeetCode题解(python) 1002. 查找常用字符 题目描述: 给定仅有小写字母组成的字符串数组 A,返回列表中的每个字符串中都显示的全部字符(包括重复字符)组成的列表。例如,如果一个字符在每个字符串中出现 3 次,但不是 4 次,则需要在最终答案中包含该字符 3 次。 你可以按任意顺序返回答案。 示例 1: 输入:["bella","label","roller"] 输出:["e",...

Marshal Zheng的博客 749

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

tzcoder:3283有穷自动机

代码 import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; public class Main { public static void main(String[] args) { // TODO Auto-generated method stub ...

qq_30113821的博客 1457

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

TZOJ练习-8248: King‘s Ruins

高维偏序(可能是板子题?)

weixin_73623214的博客 591

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

TZC Python 基础编程 121-130题

126、5957-倒着输出a与b之间的所有偶数。124、6856-倒着输出1到n中的奇数。125、5958-倒着输出1到n中的偶数。121、5953-求1到n中的偶数的和。128、6835-超市收银系统。122、5894-被17整除。123、4735-循环水题2。127、6975-小z的账单。129、3296-汉堡包。130、6641-压岁钱。

448

推荐开源项目:Transcoder——强大的视频转码库

在数字媒体的处理中,视频转码是一个不可或缺的部分,尤其在移动应用中,高效的视频压缩和转码能力成为了用户体验的重要因素。今天,我要向大家推荐一个专为Android设计的开源项目——**Transcoder**。它能帮助开发者快速、高效地将视频文件转码成MP4格式,并且支持音频处理,充分利用设备的硬件加速功能。 ## 1、项目介绍 Transcoder是一个API 18+兼容的Android视频转

gitblog_00071的博客 1515

红色警报 天梯赛 (并查集)

红色警报   战争中保持各个城市间的连通性非常重要。本题要求你编写一个报警程序,当失去一个城市导致国家被分裂为多个无法连通的区域时,就发出红色警报。注意:若该国本来就不完全连通,是分裂的k个区域,而失去一个城市并不改变其他城市之间的连通性,则不要发出警报。 输入格式: 输入在第一行给出两个整数N(0  N \le≤ 500)和M(\le≤ 5000),分别为城市个数(于是默认

Coding 1948

C++头文件<bits/stdc++.h>详解

你知道C++头文件是什么吗?快来看看吧!

peter_code的博客 1万+

TOJ_5474_学习之一个等式(威尔逊定理)

题目连接:链接:http://www.tzcoder.cn/acmhome/problemdetail.do?method=showdetail&id=5474 描述 x! mod (x+1) = x zzx和city发现了如上的一个等式,想解方程求出x的值,却发现有许多x的值均满足这个等式,随着x的增加zzx发现阶乘太难算,于是叫city写一个大数模拟,而city沉迷于找规律不可自拔。所以现在zzx想请你帮忙求一下对于一个大数x是否满足这个等式。 输入 输入数据有多组,输入到文件结束为止。

__1_1__的博客 704

C语言tzoj1067答案,zoj 1067

输入一组RGB颜色列表,每行一个颜色,是三个从0~255的整数前16行是目标颜色组,-1 -1 -1表示结束16组颜色以后接下来的几行是需要判断的,看它和哪个颜色的距离D最小,找出这个对应的颜色注意空格括弧等等1 #include2 #include3 using namespace std;45 struct Color6 {7 int R,G,B;8 }map[16];910 int ...

weixin_34310726的博客 327

输入数据有多组。 每组一行,为两个整数A, B。 输入以0 0结束。

#include int main() { int c[100],i,t=0,a,b; scanf("%d%d",&a,&b); if(a==0&&b==0)return 0; while(a!=0&&b!=0) {c[t]=a+b;t++;scanf("%d%d",&a,&b);} for(i=0;i<t;i++)printf("%d\n",c[i]);

hyc的博客 2万+

浏览器上的IDE:code-server安装——服务器版的vscode

code-server服务器版的vscode前置需求code-server简介:code-server的优势(官方给出的两个优点):code-server对服务器的配置需求:code-server的搭建下载code-server的最新版本部署code-server 本文所使用的环境配置: 服务器环境:阿里云ecs 2c4g 操作系统:centos 7.3 前置需求 Linux基础——Li...

NoBugNoLife的博客 2万+

5867: 桃子的项链

5867: 桃子的项链 http://www.tzcoder.cn/acmhome/problemdetail.do?&method=showdetail&id=5867 Time Limit(Common/Java):1000MS/3000MS Memory Limit:65536KByte Description 桃子喜欢收藏,尤其是对项链有着奇怪的要求:每颗...

Willen_的博客 388

Python编程入门教程

http://www.tzcoder.cn/acmhome/news.do?method=newsDetail&id=2c903bb4796f8da101798391db600b2e 本博客原文地址:Python编程入门教程(以在线评测平台为载体) - 暴力都不会的蒟蒻 - 博客园,原文体验更佳 如果你是一名浙江2020级及以后的高中生要学习Python,抑或是一位科学工作者要学习Python,抑或是一名熟悉C/C++想扩展自己的技术栈来学习Python,抑或是一位小朋友在学习Python,以下

2万+
上一篇: 浙江农林大学ACM集训队2019级队长退役回忆录(未实际退役版本)
StandNotAlone
博客等级 码龄7年 338粉丝 47原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值