军训报数(哈希+素数判断+状态压缩)

题目描述 
Nosoul经过多年勤学苦练,终于考上大学了!上大学的第一堂课,当然是军训啦~ 
时间过的真快,一上午的军训眨眼就过去了,又到了午饭时间了。这次,教官突发奇想要玩个游戏。游戏规则是:所有的学生站成一排,从个头最小的排头 Nosoul开始报数;凡是报到的数为素数(即除1和它本身,没有其他约数的数)的同学,即可出列去吃午饭,剩下的同学向前补齐;然后继续第二次从头开始 报数,依然是报到的数为素数的即可出列去吃午饭;然后第三次报数„„直到队列里没有素数为止。 
额„貌似按照这个规则,Nosoul永远也吃不上午饭啊,哈哈,不管他,谁让他是Nosoul呢^_^ 
输入 
本题有多个测试用例。输入数据的第一行是一个数N,代表有N个测试用例。接下来的N行,每行只有一个正整数M(M<1000000),代表总共的学生人数。 

输出 

输出共有

N

行。每行一个整数

T

,对应输入的学生人数。

T

代表总共报数

T

次之

后,队列里只剩

Nosoul

一人。

 

样例输入

 

样例输出

 

2

输出共有

N

行。每行一个整数

T

,对应输入的学生人数。

T

代表总共报数

T

次之

后,队列里只剩

Nosoul

一人。

 

样例输入

 

样例输出

 

2

输出共有

N

行。每行一个整数

T

,对应输入的学生人数。

T

代表总共报数

T

次之

后,队列里只剩

Nosoul

一人。

 

样例输入

 

样例输出

 

2

输出共有N行。每行一个整数T,对应输入的学生人数。T代表总共报数T次之后,队列里只剩Nosoul一人。 
样例输入 
3 3 4 5 
样例输出 
1 2 2 


#include <stdio.h> 
#include <math.h>   
bool isPrime(int x) { 
    if(x==1) 
        return false;     
    int t = sqrt(x) + 1;  
   for(int i=2; i<t; i++)     { 
        if(x%i==0) 
            return false;     } 
    return true; 
}   
int hash[1000000]; 
int main() { 
    int i, n, m, ans, t;     
    hash[1] = 0; 
    for(i=2; i<1000000; i++)     { 
        if(isPrime(i)) 
            hash[i] = hash[i-1] + 1;         
        else 
            hash[i] = hash[i-1];     
     } 
    scanf("%d", &n);     
    while(n--)     { 
        ans = 0; 
        scanf("%d", &m);         
        t = m; 
        while(t!=1)         { 
            t = t - hash[t];            
           ans++;         
        } 
        printf("%d\n", ans);     
    } 
    return 0; 
} 



你可能感兴趣的:(算法,ACM)