HDU 2554 N对数的排列问题

本文介绍了一种解决HDU2554问题的方法,通过将问题转化为方程组,利用数学推导找到满足特定条件的双胞胎排列方案。文章详细解释了推导过程,并给出了判断解存在的条件及简洁的实现代码。

LINK:HDU 2554

这是昨天晚上小练里面比较有趣的一道题~我在做的时候思路错了,以为数字的排列会有规律,结果后面发现就算有也很难找......╮(╯▽╰)╭

看了网上的题解,有一种恍然大悟的感觉,就直接把它当做方程来解,只要符合题意的x,y存在即可~

题解:

      假设双胞胎数为n,那么就共有2n个人,把双胞胎分开,分别记为A类和B类。在进行排列时,ak代表【年龄为k,同时所属分类为A的人在排列中的位置】,同理,bk则表示【年龄为k,所属分类为B的人在排列中的位置】~(注:在此假设ak<bk,sum(i)表示从1到i求和)

      若该排列能符合题目要求,那么:

      ①bk-ak=k+1;(k=1,2,3,......,n)

      ②sum(bk-ak)=sum(k+1)=2+3+...+(k+1)=k*(k+3)/2;

      ③当ak,bk满足以上两个条件时,又应当有2k个位置来放双胞胎

因此:sum(ak+bk)=1+2+3+......+2*k=k*(1+2k);

      ④同时:sum(ak+bk)=sum(2*ak+(bk-ak))=2*sum(ak)+sum(bk-ak)=2*sum(ak)+k*(k+3)/2;

      只有当所有双包胎都符合上面所有式子,那么才存在符合题意的排列,SO~应为共2n个数,那么k=n时,bk=2n,ak=2n-n-1=n-1;

由上式可得:sum(ak)=n*(3n-1)/4,sum(bk)=5*n*(n+1)/4;当上面两个式子为整数时,这个n是符合条件的~╮(╯▽╰)╭

代码:

 1 #include<cstdio>
 2 #include<cstring>
 3 int main()
 4 {
 5     int n;
 6     while( ~scanf("%d", &n) && n)
 7         if(n%4 == 0 || (n+1) % 4 == 0)
 8             puts("Y");
 9         else puts("N");
10     return 0;
11 }

//memory:228KB     time:31ms

 

转载于:https://www.cnblogs.com/teilawll/p/3275128.html

Java代码HDU4109-重新排列指令问题是一个经典的算法问题,要我们重新排列一系列指令,使得最终结果符合特定条件。以下是一个详细的解决方案: ```java import java.util.*; public class Main { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); int T = scanner.nextInt(); while (T-- > 0) { int n = scanner.nextInt(); int[] a = new int[n]; for (int i = 0; i < n; i++) { a[i] = scanner.nextInt(); } System.out.println(canRearrange(a, n) ? "Yes" : "No"); } scanner.close(); } private static boolean canRearrange(int[] a, int n) { // 创建一个布尔数组来记录每个数字是否被使用过 boolean[] used = new boolean[n]; // 创建一个数组来存储每个数字的目标位置 int[] target = new int[n]; for (int i = 0; i < n; i++) { target[a[i] - 1] = i; } // 尝试重新排列指令 for (int i = 0; i < n; i++) { if (!used[i]) { int j = i; int cycleLength = 0; while (!used[j]) { used[j] = true; j = target[j]; cycleLength++; } if (cycleLength % 2 != 0) { return false; } } } return true; } } ``` ### 解释 1. **输入处理**:首先读取测试用例的数量T,然后对于每个测试用例,读取指令的数量n和指令的初始排列a。 2. **目标位置计算**:通过创建一个`target`数组来存储每个数字的目标位置。 3. **重新排列检查**:使用一个布尔数组`used`来记录每个数字是否被使用过。遍历每个数字,如果它还没有被使用过,则开始一个新的循环,并计算循环的长度。如果循环的长度是奇数,则返回`false`,否则继续。 4. **输出结果**:如果所有循环的长度都是偶数,则返回`true`,否则返回`false`。 ### 关键点 - **循环检测**:通过记录每个数字是否被使用过,避免重复计算。 - **奇偶性检查**:只有当所有循环的长度都是偶数时,才能成功重新排列指令。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值