计算一个给定数x与3和4的关系:x = 3 * n + 4 * m,并找到|n-m|的最小值

本文提供了一种使用Java解决特定数学问题的方法:给定一个大于5的整数x,找到x与3和4之间的线性组合关系x=3*n+4*m,并找出|n-m|的最小值。文章中分享了一个递归解决方案,但在输入较大数值时会出现栈溢出的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在网上看到的一个笔试题,以下是我自己的Java解法,但是当输入数过大时,会栈溢出。我在网上没找到该题的其他解法,希望有会的可以帮我解答一下。

/**
 * 给定一个数x(x>5),找到该数与3、4之间的关系。
 * 关系如下:x=3*n+4*m,然后找到|n-m|的最小值。
 * 其中:6=3*2+4*0
        7=3*1+4*1
		8=3*0+4*2
		9=3*3+4*0
 * @author ZJ
 *
 */
public class ThreeAndFour {

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int num = 1;
		System.out.println("请输入一个>5的整数:(输入-1结束)");
		while(true){
			num = sc.nextInt();
			if(num == -1)
				break;
			calRelation(num, 0, 0, Integer.MAX_VALUE);
		}
	}
	
	/**
	 * 计算num与3和4的关系,并计算|n-m|的最小值
	 * @param num	输入的数
	 * @param n		与3的关系
	 * @param m		与4的关系
	 * @param min	|n-m|的最小值
	 */
	public static void calRelation(int num, int n, int m, int min){
		//能除3除尽,说明出现一种可能结果
		if(num % 3 == 0){
			int n1 = num / 3;
			n += n1;
			min = Math.min(min, Math.abs(n-m));
			System.out.println(n + "," + m);
			//最初计算肯定是n>=m,当n<m后,求得差绝对值>min后,后面的结果的差值只会比min大,因此如果不是要计算所有结果,到此就可以计算出min的值了
			if(n < m && min < Math.abs(n-m)){
				System.out.println("----min:" + min);
				return;
			}
			//如果最后除3只剩1或不到1了,那么所有可能的结果已经计算完了,可以结束输出min了
			if(n1 <= 1){
				System.out.println("min:" + min);
			}else{		//否则,计算其他可能结果
				n -= n1;
				num -= 4;
				m ++;
				calRelation(num, n, m, min);
			}
		}else{	//除不尽3,递归计算m++后的可能结果
			num -= 4;
			if(num >= 3){
				m ++;
				calRelation(num, n, m, min);
			}else{
				System.out.println("min:" + min);
			}
		}
	}
}


差为给定K13167 - 差为给定 题目描述 给定一个包含N个各不相同的整序列A,接下来进行M次查询,每次查询给定一个X,请查询X是否可以通过序列A中的两个元素的差获得,如果可以输出YES,否则输出NO。 输入格式 第1行:两个空格分隔的正整NM,分别表示序列A中元素的查询的次。 第2行:N个空格分隔的整,表示序列A中的N个整。 第3行:M个空格分隔的整,表示M次查询的整X。 输出格式 输出M行,对于每次询问,输出一行YES 或 NO。 输入输出样例 输入样例1: 5 3 1 3 5 7 9 4 10 6 输出样例1: YES NO YES 说明 【据范围】 1 <= N <= 100000, 1 <= M <= 10; -10^9 <= X <= 10^9,-10^9 <= 序列A中的元素 <= 10^9, K13167 - 差为给定 题目描述 给定一个包含N个各不相同的整序列A,接下来进行M次查询,每次查询给定一个X,请查询X是否可以通过序列A中的两个元素的差获得,如果可以输出YES,否则输出NO。 输入格式 第1行:两个空格分隔的正整NM,分别表示序列A中元素的查询的次。 第2行:N个空格分隔的整,表示序列A中的N个整。 第3行:M个空格分隔的整,表示M次查询的整X。 输出格式 输出M行,对于每次询问,输出一行YES 或 NO。 输入输出样例 输入样例1: 5 3 1 3 5 7 9 4 10 6 输出样例1: YES NO YES 说明 【据范围】 1 <= N <= 100000, 1 <= M <= 10; -10^9 <= X <= 10^9,-10^9 <= 序列A中的元素 <= 10^9,
06-22
## **题目描述** 给出一个长度为 $n$ 的列 $\{a_1, a_2, a_3, \dots, a_n\}$,以及 $m$ 组询问 $(l_i, r_i, k_i)$。对于每组询问,求在区间 $[l_i, r_i]$ 中有多少种字,其在该区间内的出现次 $k_i$ 互质(即 $\gcd(\text{出现次}, k_i) = 1$)。 ## **输入格式** 第一行包含两个正整 $n$ $m$,分别表示列长度询问次。 第二行包含 $n$ 个正整 $a_i$,描述该列。 接下来 $m$ 行,每行包含三个正整 $l_i, r_i, k_i$,描述一次区间询问。 ## **输出格式** 输出 $m$ 行,每行一个,表示对应询问的答案。 ## **样例** #### 样例输入 ```plain 10 5 1 1 1 1 1 2 2 2 2 2 4 7 2 4 7 3 4 8 2 4 8 3 3 8 3 ``` #### 样例输出 ```plain 0 2 1 1 0 ``` ## **据范围提示** #### **样例解释** - 第一组询问 $[4,7]$:元素为 $[1,1,2,2]$,字 $1$ 出现 $2$ 次($\gcd(2,2)=2≠1$),字 $2$ 出现 $2$ 次(不互质),故答案为 $0$。 - 第二组询问 $[4,7]$:字 $1$ 出现 $2$ 次($\gcd(2,3)=1$),字 $2$ 出现 $2$ 次($\gcd(2,3)=1$),故答案为 $2$。 #### **据范围** - $1 \le n, m \le 5 \times 10^4$ - $1 \le a_i \le n$ - $1 \le l_i \le r_i \le n$ - $1 \le k_i \le n$ #include <bits/stdc++.h> #define ll long long using namespace std; const ll N=5e4; struct node{ ll l,r,k,f; }q[N+5]; ll n,m; ll a[N+5]; ll blk[N+5],lenb; bool jo[N+5]; ll pre[N+5],nxt[N+5]; ll head,tail; ll lp=1,rp,s; ll cnt[N+5],f[N+5]; ll ans[N+5]; ll gcd(ll a,ll b){ return b?gcd(b,a%b):a; } bool cmp(node l1,node l2){ if(blk[l1.l]==blk[l2.l]){ if(blk[l1.l]&1) return l1.r<l2.r; return l1.r>l2.r; } return blk[l1.l]<blk[l2.l]; } void addd(ll x){ if(x<1 || x>n || jo[x]) return; jo[x]=1; pre[x]=head; nxt[x]=nxt[head]; pre[nxt[head]]=x; nxt[head]=x; return; } void dell(ll x){ if(x<1 || x>n || !jo[x]) return; jo[x]=1; nxt[pre[x]]=nxt[x]; pre[nxt[x]]=pre[x]; return; } void add(ll x){ f[cnt[a[x]]]--; if(f[cnt[a[x]]]==0) dell(cnt[a[x]]); cnt[a[x]]++; f[cnt[a[x]]]++; if(f[cnt[a[x]]]==1) addd(cnt[a[x]]); return; } void del(ll x){ f[cnt[a[x]]]--; if(f[cnt[a[x]]]==0) dell(cnt[a[x]]); cnt[a[x]]--; f[cnt[a[x]]]++; if(f[cnt[a[x]]]==1) addd(cnt[a[x]]); return; } void solve(ll l,ll r){ while(l<lp){ lp--; add(lp); } while(lp<l){ del(lp); lp++; } while(rp<r){ rp++; add(rp); } while(r<rp){ del(rp); rp--; } return; } int main(){ scanf("%lld%lld",&n,&m); lenb=(ll)sqrt(n); ll sx=1; for(ll i=1;i<=n;i++){ blk[i]=sx; if(i%lenb==0) sx++; } for(ll i=1;i<=n;i++) scanf("%lld",&a[i]); for(ll i=1;i<=m;i++){ scanf("%lld%lld%lld",&q[i].l,&q[i].r,&q[i].k); q[i].f=i; } tail=n+1; nxt[head]=tail; pre[tail]=head; f[0]=n; sort(q+1,q+m+1,cmp); for(ll i=1;i<=m;i++){ solve(q[i].l,q[i].r); for(ll j=nxt[head];j!=tail;j=nxt[j]){ if(gcd(j,q[i].k)==1) ans[q[i].f]+=f[j]; // cout<<j<<" "; } } for(ll i=1;i<=m;i++) printf("%lld\n",ans[i]); return 0; } 过不了样例,修正代码错误标出
最新发布
08-05
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值