1001小凯逛超市

题意:选择n种商品,每种商品可无限选择,第 i 种商品价值为gi,体积都是1,你需要输出在总价格不超过v的前提下填满m背包的方案数,答案 % 1e9+7。

输入:有 T 组数据,1≤T≤5 ,  1≤n,m,V,gi≤400 。

输出:对于每组数据,输出一个数 ans, 表示方案数取模之后的值。

思路:完全背包问题,定义f[ j ][ k ] : 达到总价格为j ,体积为k的总方案数

                                    初始化:memset( f,0,sizeof(f) ) , f[0][0]=1

                                    转移方程:f[ j ][ k ] = f[ j ][ k ]+f[ j - x ][k – 1] (x:当前商品的价值)

           计算答案Ans :  for(int i=1;i<=v;i++)   ans=(ans+f[ v ][ m ])%M。

代码:

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N=500,M=1e9+7;
int f[N][N];

signed main(){
	
	int T;
	cin >> T;
	
	int n,m,v,x;
	while(T--){
		cin >> n >> m >> v;
		
		memset( f,0,sizeof(f) );    //初始化动态数组
		
		f[0][0]=1;                  // 初始化不选任何物品且价值为 0 的方案数为 1
		
		for(int i=1;i<=n;i++){      
			cin >> x;
			for(int j=x;j<=v;j++){      //选取物品的总价值 
				for(int k=1;k<=m;k++){  //选取物品的总体积 
					f[j][k] = (f[j][k]+f[j-x][k-1])%M;
				}
			}
		}
		
		int ans=0;
		for(int i=1;i<=v;i++) {         //遍历体积为m的方案数 
			ans =  (ans + f[i][m])%M;
		} 
		
		cout << ans <<'\n';
	}
    return 0;
}

1006小凯在长跑

题意:一个常规跑道,由两个半圆、两条直道连接组成,圆的半径为r,直道长度为2d。现在给出一个坐标(x,y),求这个点走到跑道的最近距离。

输入:有 T组数据,1≤T≤1e5,1≤d,r≤1e4,  −1e4≤x,y≤1e4。

输出:T行,每行一个整数,四舍五入后可到固定路径的最短距离长度。

思路:将x,y都取abs,将范围缩小到第一区间,因为四个区间都是对称等区域的,所以不会影响答案,然后再讨论坐标在直跑道内/外,还是在圆跑道内外即可。

1、当 y 小于等于 d 时,说明点在某个特定的水平范围内。此时比较 x 和 r 的大小,计算它们的差值,差值的绝对值就是所求的距离。

2、当 y 大于 d 时,点不在上述水平范围内。此时需要计算点 (x, y) 到圆心(这里圆心可以理解为 (0, d))的距离 len,使用勾股定理 sqrt(x * x + (y - d) * (y - d)) 来计算。然后比较 len 和 r 的大小,计算它们的差值并四舍五入得到最终结果。

代码:

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

int main(){
	int T;
	cin >> T;
	
	int d,r,x,y;
	while(T--){
		cin >> d >> r >> x >> y;
		
		x=abs(x),y=abs(y);
		
		if(y<=d){
			if(x>r) cout << x-r;
			else cout << r-x;
		}
		else{
			 // 计算点 (x, y) 到圆心 (0, d) 的距离
			double len=sqrt((x*x)+(y-d)*(y-d));    
			
			if(len>r) cout << round(len-r);
			else cout << round(r-len);
		}
		cout <<'\n';
	}
	return 0;
}

1010小凯做梦

题意:存在一棵树,无向边,n个节点,有n-1条边,一条边从点u到点v的边权为w,dis(i,j)表示 i 号节点跟 j 号节点之间的距离对 2 取模之后的结果,问有多少对 ( i,j,k ) 满足, dis(i,j) = dis(j,k) = dis(i,k) , (1 <= i , j , k <= n) ,注意 i,j,k 可以相等。

输入:有 T组数据,1≤T≤5,  1≤n≤5∗1e5,  1≤u,v≤n,1  ≤w≤1e9 。

输出:共T行,对于每组数据,输出一个数 ans 表示有多少对( i,j,k )满足条件。

思路:因为%2后dis要么0(偶),要么1(奇),可以建立无向树:v[u]={v,w}(u->v且边权w), v[v]={u,w},以任意根节点dfs(x,fa,u)搜索:x:当前节点,fa:父节点,u:当前步奇/偶,return{奇数总个数,偶数总个数},分奇偶两组,每组中任意一个数都可以填入(i,j,k)三个位置,答案ans= pow(奇数总个数,3)+pow(偶数总个数,3)。

代码:

#include <bits/stdc++.h>
using namespace std;
#define int long long 
#define fi first
#define se second 
typedef pair<int,int>PII;
const int N=5e5+10;
vector<PII>v[N];

PII dfs(int x,int fa,int u){   //x:当前节点,fa:父节点,u:当前步奇/偶 
	PII res;                   
	if(u==0) res={0,1};        // 如果当前步为偶数,初始化奇数个数为 0,偶数个数为 1
	else res={1,0};			   // 如果当前步为奇数,初始化奇数个数为 1,偶数个数为 0
	
	for(auto p:v[x]){
		int l=p.fi,w=p.se;
		if(l==fa) continue;
		
		// 递归调用 dfs 函数,计算从邻接节点开始的路径长度的奇偶性数量
		PII val=dfs(l,x,(u+w)%2);
		
		res.fi+=val.fi;
		res.se+=val.se;
	} 
	return res;
}

signed main(){
	ios::sync_with_stdio(0);
	cin.tie(0); 
	int T;
	cin >> T;
	
	int n,l,r,w;
	while(T--){
		
		cin >> n;
		for(int i=1;i<=n;i++) v[i].clear();
		
		n--;
		while(n--){// 读取边的两个端点 l 和 r 以及边的权重 w
			cin >> l >> r >> w;
			v[l].push_back({r,w});
			v[r].push_back({l,w});
		}
		
		PII d=dfs(1,0,0);
		int ans= pow(d.fi,3)+pow(d.se,3);  
		cout << ans<<'\n';
	}
	return 0; 
}

1008小凯想要MVP!

题意:在一个长度为n数组中每元素Ci满足1≤Ci≤m , 是否存在两个数组:

1、长度相同,2、元素和相同,3、两个子序列不能相交。(即不能取相同位置上的数),存在“YES”,否则“NO”。

输入:有T组数组, 1≤T≤20,  1≤n,m≤2∗1e5 。

输出:共T行,对于每组数据,如果能找到满足条件的子序列,输出 YES ,否则输出 NO 。

思路:因为两个子序列的长度相同,总和一样,如果存在满足条件的情况必定有两个数的差值同时存在两序列中,否则无法构造出两个等长等和的子序列,输出“NO”即可。

数组sort排序后,每两个相邻的差值存在map中,当map的值==2且差值不相邻(i,j,k,j-i==k-j为两个差值相邻)或者map的值>2 , 则“YES”,否则“NO”。

代码:

#include <bits/stdc++.h>
using namespace std;
const int N=2e5+10;
map<int,int>mp,vp;
int t[N];

int main(){
	ios::sync_with_stdio(0);
	cin.tie(0); 
	int T;
	cin >> T;
	
	int n,m;
	while(T--){
		cin >> n >> m;
		
		int p=0;
		vp.clear(),mp.clear();
		
		for(int i=0;i<n;i++) {
			cin >> t[i];
			vp[t[i]]++;
			if(vp[t[i]]==2) p=1;
		}
		
		if(p) {
			cout << "YES"<<'\n';
			continue;
		}
		
		sort(t,t+n);
		
		for(int i=0;i<n;i++){
			int u=t[i+1]-t[i];
			mp[u]++;
			if(i-1>=0&&mp[u]==2&&u!=t[i]-t[i-1]) p=1;
			else if(mp[u]>2) p=1;
		}
		if(p) cout << "YES";
		else cout << "NO";
		cout << '\n';
	} 
	return 0; 
}

1009小凯取石子

题意:现有 n 个石子,小凯和 Kc0 轮流从中取出 1 或 4 颗石子,Kc0 先手,取走最后一颗石子的人即为胜者。

由于 Kc0 太笨了,所以他每次只会等概率随机地想要取走 1 颗或者 4 颗石子。如果 Kc0 想要取走 4 颗石子但是剩下的石子不足 4 颗,那么他会掀桌走人并被判负。

小凯非常聪明,并且他知道 Kc0 的策略。那么小凯最终获胜的概率是多少?

输入:表示有 T组数据,T<=100, 1<=n<=1e9。

输出:对于每组数据输出一行一个整数,表示小凯获胜的概率对 998244353998244353 取模后的结果。

推导打表找规律:

打表代码:

#include <bits/stdc++.h>
using namespace std;
typedef array<int,2> ar2;
typedef pair<int,int>PII;
map<int,ar2>m;

ar2 sg(int x){
	if(m.count(x)) return m[x];
	
	ar2 u=sg(x-2);
	ar2 v=sg(x-5);
	ar2 w=sg(x-8);

	ar2 d1,d2;
	
	double du=1.0*u[0]/u[1], dv=1.0*v[0]/v[1], dw=1.0*w[0]/w[1];
	if(du>dv) d1=u;
	else d1=v;
	d1[1]*=2;
	
	if(dv>dw) d2=v;
	else d2=w;
	d2[1]*=2;

	ar2 res={d1[0]*d2[1]+d1[1]*d2[0],d1[1]*d2[1]};
	int g=__gcd(res[0],res[1]);
	res[0]/=g,res[1]/=g;

	
	return m[x]=res;
}

int main(){         //《打表代码》 
	m[1]={1,2};
	m[2]={1,1};
	m[3]={3,4};
	m[4]={1,2};
	m[5]={1,1};
	m[6]={1,2};
	m[7]={1,1};
	m[8]={7,8}; 
	
	int n;
	cin >> n;
	
	for(int i=1;i<=n;i++){
		auto x=sg(i); 
		cout << i <<" "<< m[i][0]<<" "<< m[i][1]<<endl;
	}
	return 0; 
}

AC代码:

#include <bits/stdc++.h>
#define int long long
using namespace std;
int n=0,m=0,k=0;
const int mod =998244353;

int qc(int a,int b)
{
    int ans=1;
    while (b)
    {
        if(b&1)ans*=a;
        a*=a;
        b>>=1;
        ans%=mod;
        a%=mod;
    }
    return ans%mod;
}

signed main ()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    int T;
    cin>>T;
    while (T--)
    {
		cin>>n;
	    if(n==1){
		cout<<499122177<<"\n";
		continue;
		}
	    int x=n%5,y=n/5;
	    if(x==3) y+=2;
	    if(x==4) y+=1;
	    if(x==2||x==0){
		cout<<1<<"\n";
		continue;
		}
	    int fm=qc(2,y)%mod;
	    int fz=(fm-1+mod)%mod;
	    cout<<(fz%mod*qc(fm,mod-2)%mod)%mod<<"\n";
	}
	return 0;
}

2025“钉耙编程”中国大学生算法设计春季联赛(6)题解链接:

HDU 2025“钉耙编程”中国大学生算法设计春季联赛(6)(补题)-CSDN博客

2025“钉耙编程”中国大学生算法设计春季联赛(7)题解链接:

HDU 2025“钉耙编程”中国大学生算法设计春季联赛(7)(补题)-CSDN博客

更多推荐