先说一下全排列:

对于R={r1,r2,…,rn},进行n个元素的全排列,设Ri=R – {ri}。结合X元素的全排列记为Perm(X)(ri)Perm(X)表示在全排列Perm(X)的每个排列前面加上前缀ri的得到的序列。R的全排列可归纳定义如下:

n=1时,Perm(R)=(r),其中rR中的唯一元素;

n>1时,Perm(R)(r1)Perm(R1), (r2)Perm(R2),…, (rn)Perm(Rn)构成。

显然,部分排列,只要控制递归结束条件即可。

 

再说组合:

组合与排列相比,忽略了元素的次序,因此我们只需将元素按编号升序排列(或则其他的规则)即可。
代码如下:


public class Main {
    
    
static int count;
    
public static void main(String[] args) {
        
int a[] = {1234};
        count 
= 0;
        permutation(a, 
04);
        System.out.println(
"count=" + count);
        
        count 
= 0;
        combination(a, 
030);
        System.out.println(
"count=" + count);
    }

    
static void combination(int a[], int nowp, int m, int left){//zuhe
        /*
         * 求a[]中m个元素的组合
         * nowp表示当前已经组合好的元素的个数
         * left,只能选择编号为left和它之后的元素 进行交换
         
*/

        
if(nowp == m){
            count
++;
            
for(int i = 0; i < m; i++){
                System.out.print(a[i] 
+ " ");
            }

            System.out.println();
        }

        
else{
            
for(int i = left; i < a.length; i++){
                swap(a, nowp, i);
                combination(a, nowp 
+ 1, m, i + 1);
                swap(a, nowp, i);
            }

        }

    }

    
static void permutation(int a[], int nowp, int m){// pailie
        /*
         * 求a[]m个元素的排列
         * nowp,当前已经排列好的元素的个数
         
*/

        
        
if(nowp == m){
            count
++;
            
for(int i = 0; i < m; i++){
                System.out.print(a[i] 
+ " ");
            }

            System.out.println();
        }

        
else{
            
for(int i = nowp; i < a.length; i++){
                swap(a, i, nowp);
                permutation(a, nowp 
+ 1, m);
                swap(a, i, nowp);
            }

        }

    }

    
static void swap(int a[], int n, int m){
        
int t = a[n];
        a[n] 
= a[m];
        a[m] 
= t;
    }


}


posted @ 2013-07-06 10:54 小鼠标 阅读(1312) | 评论 (0)编辑 收藏

题意:

给定两个非负数,可以用较小那个数的任意正整数倍数去减较大那个数,但要保证结果非负。两个人轮流操作,结果中先出现0的那个人获胜。

 

第一次做博弈题,不知如何下手。这里认真分析一下。

 

假设两个数a b,他们的大小关系无非是a>b,a<b,a==b中的一种,对本题二样前两种其实是同一种情况,第三种情况时结果已经出来了(此时轮到谁谁获胜)。

 

我们再来讨论a>ba<b)的情况,又可细分为:

b<a<2 * b (1)

a == 2 * b (2)

a >2*b (3)

对情况(1,选手没得选,只能用较小的树去减较大的数,下一个状态一定是ba%b。也就是说这种状态的出现不会影响最终结果。

情况(2,显然,也可以结束游戏了,当前选手赢了。

情况(3,此时选手可以决定下一个状态是下面状态中的一种:

a-b, b

a-2*b, b

a-3*b, b

.

.

.

a%b+b, b k-1

b, a%b k

由于两个选手必须轮流操作,因此,两相邻的状态的输赢结果一定相反。而此时,选手恰恰可以决定是到状态(k-1)还是到状态(k(状态(k-1)的下一个状态一定是状态(k),因为情况(1)),也就是说此时选手能决定自己的输赢

 

综上我们可以得到如下结论

出现下述情况之一的就可断定当前选手获胜:

1.a==b

2.a>=2*b

 

细节:如果一开始输入数据为a0,本题认为Ollie wins

import java.io.*;
import java.util.*;

class Main {
    
    static boolean firstWin;
    public static void main(String[] args) throws IOException{
        int a, b;
        Scanner sc = new Scanner(System.in);
        
        a = sc.nextInt();
        b = sc.nextInt();
        while(a != 0 || b != 0){
            firstWin = true;//初始认为Stan wins
            if(a >= b)
                get(a, b);
            else
                get(b, a);
            
            if(firstWin)
                System.out.println("Stan wins");
            else
                System.out.println("Ollie wins");
            a = sc.nextInt();
            b = sc.nextInt();
            
        }
    }
    public static void get(int a, int b){//a >= b
        if(a == b)
            return;
        if(b == 0){//边界情况,如果一开始输入是b为零,我们认为Ollie wins
            firstWin =  !firstWin;
            return;
        }
        if(a / b >= 2)
            return;
        
        firstWin =  !firstWin;
        get(b, a % b);
    }
}

 

posted @ 2013-05-04 16:21 小鼠标 阅读(239) | 评论 (0)编辑 收藏

Counting fractions

TimeLimit: 2000MS  MemoryLimit: 65536 Kb

Totalsubmit: 39   Accepted: 6  

Description

Consider the fraction, n/d, where n and d are positive integers. If <= d and HCF(n,d)=1, it is called a reduced proper fraction.

If we list the set of reduced proper fractions for d <= 8 in ascending order of size, we get:

1/8, 1/7, 1/6, 1/5, 1/4, 2/7, 1/3, 3/8, 2/5, 3/7, 1/2, 4/7, 3/5, 5/8, 2/3, 5/7, 3/4, 4/5, 5/6, 6/7, 7/8

It can be seen that there are 21 elements in this set.

How many elements would be contained in the set of reduced proper fractions for d <= x?

Input

The input will consist of a series of x, 1 < x < 1000001.

Output

For each input integer x, you should output the number of elements contained in the set of reduced proper fractions for d <= x in one line.

Sample Input

3

8

Sample Output

3
21

Hint

HCF代表最大公约数

这里主要说一下素数筛法,该方法可以快速的选取出1~N数字中的所有素数。时间复杂度远小于O(N*sqrt(N))
方法为:从2开始,往后所有素数的倍数都不是素数。最后剩下的数都是素数。
再说说欧拉公式,用来解决所有小于n中的数字有多少个与n互质,用Ψ(n)表示。
Ψ(n)=n*(1-1/q1)*(1-1/q2)*……*(1-1/qk),n为和数,其中qi为n的质因数。
Ψ(n)=n-1,n为质数
注意:关于数论的题很容易超过int类型的范围,多考虑用long long类型。
欧拉函数请参阅:http://zh.wikipedia.org/zh-cn/%E6%AC%A7%E6%8B%89%E5%87%BD%E6%95%B0

代码

 

posted @ 2013-04-30 21:26 小鼠标 阅读(1277) | 评论 (0)编辑 收藏
     摘要: 最大值 TimeLimit: 1000MS  MemoryLimit: 65536 Kb Totalsubmit: 161   Accepted: 4   Description Little Ming很喜欢训练自己的快速读能力,他最近找到一种新的考验并训练快速读能力的方法,在一行具...  阅读全文
posted @ 2013-04-28 18:47 小鼠标 阅读(235) | 评论 (0)编辑 收藏
括号的两种不同表示间的转换。
解题思路比较偷懒:先将括号恢复成我们喜欢看的形式,然后再转换成w型的表示方式。
代码

posted @ 2013-04-18 22:44 小鼠标 阅读(147) | 评论 (0)编辑 收藏
题意:
求给定矩阵的最大子矩阵和。
先来回顾一下一维的最大子段和问题:
给定一个序列a[n],求a[n]的最大子段和。
DP的递推公式为b[j] = max{b[j - 1] + a[j], a[j]}. 其中b[j]表示a[n]中包含b[j]的最大子段和。时间复杂度为O(n)
对于二维矩阵而言,我们可以通过把多行压缩(按列求和)成一行的方式将问题转换为一维
行压缩时枚举复杂度为O(N^2)。因此整个求解过程的时间复杂度为O(N^3)。
代码



posted @ 2013-04-17 15:32 小鼠标 阅读(265) | 评论 (0)编辑 收藏
题意:找出矩阵中的最长下降序列的长度。
解题思路:
1.回溯,时间复杂度,指数级别。这是一种很容易想到的做法,不过会超时。
2.动态规划,时间复杂度O(N^2)。相信我们都学过一维的最长上升子序列问题,这一题是一维的变形,我们只需稍加转换就可以转换为一维的。
先来回想一下一维的最长上升子序列的做法:对一个给定的节点p,我们只需枚举p前面的所有节点的最长上升子序列的长度,用p前面的节点的长度去试图更新p的长度即可。
我们如何将本题转化为一维的问题呢?我们只需将矩阵中的所有点按照他的high排序,然后按照一维的处理即可。只不过p前面的节点在更新p时还要考虑他们在矩阵中的相对位置,因为只有跟p相邻的四个点才有可能去更新p点的长度。
代码

posted @ 2013-04-16 18:36 小鼠标 阅读(391) | 评论 (0)编辑 收藏
     摘要: 题意:按照指定格式输出目录树。要求同一层下的file要按文件名排序。解题步骤:1.用deep记录当前目录深度,遇到dir,deep++,遇到] deep--2.用strlist记录所有未输出的file,用栈stack记录当前目录下的file表的开始下标。遇到]或者*则输出当前目录下的所有file,并从strlist中删除,相应的下标出栈(stack). 代码Code highlighting p...  阅读全文
posted @ 2013-04-14 22:30 小鼠标 阅读(288) | 评论 (0)编辑 收藏
     摘要: 题意:对比连个图是否相同。相同的条件是A图中每个连通的区域都在B图中有一块相同的区域与之对应。经过旋转后对应也可以。解题思路:思路一:暴力式。遍历并存储A图中所有联通的区域,然后在B中逐个寻找与之对应的图形。思路二:等价转化式。比较两个图中对应点的“连通度”是否相同。相同输出YES。空白点的连通度为0,空白点的连通度为它所在行和列与之相连的非空白点的个数。方式二非常巧妙,将...  阅读全文
posted @ 2013-04-14 20:10 小鼠标 阅读(494) | 评论 (0)编辑 收藏
     摘要: 题意:字处理程序检查输入的单词是否正确。若不正确,则按照规则在字典中找与该单词相近的单词。解题思路:按照题目给出的规则模拟。要点:要注意查找效率,遍历会超时。此处用的是TreeMap,查找效率log2(N)。 代码Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.c...  阅读全文
posted @ 2013-04-09 15:17 小鼠标 阅读(124) | 评论 (0)编辑 收藏
仅列出标题
共13页: 1 2 3 4 5 6 7 8 9 Last 
<2024年4月>
31123456
78910111213
14151617181920
21222324252627
2829301234
567891011

常用链接

随笔分类(111)

随笔档案(127)

friends

最新评论

  • 1. re: 线段树
  • 是这个样子的,所以在OJ有时候“卡住”了也不要太灰心,没准真的不是自己的原因呢。
    加油,祝你好运啦!
  • --小鼠标
  • 2. re: 线段树
  • 对于编程竞赛来说,Java所需时间一般为C/C++的两倍。合理的竞赛给Java的时间限制是给C/C++的两倍。
  • --伤心的笔
  • 3. re: poj1273--网络流
  • 过来看看你。
  • --achiberx
  • 4. re: (转)ubuntu11.10无法启动无线网络的解决方法
  • 膜拜大神。。查了一个下午资料终于在这里解决了问题。。神牛说的区域赛难道是ACM区域赛。。?
  • --Hang
  • 5. re: 快速排序、线性时间选择
  • 博主,谢谢你的文章。你的方法可以很好的处理分区基准在数组中重复的情况,书上的方法遇到这种输入会堆栈溢出。书上给出了解释但给的方法貌似不简洁。
  • --lsxqw2004

阅读排行榜