南邮 OJ 1404 取数游戏
2015-08-05 15:15
169 查看
取数游戏
时间限制(普通/Java) : 1000 MS/ 3000 MS 运行内存限制 : 65536 KByte总提交 : 90 测试通过 : 23
比赛描述
lqp刚学了辗转相除法,正不亦乐乎。will 又出来捣乱,给lqp 留了个难题。
给 N 个数,用 a1,a2…an来表示。现在will 让lqp依次取数,第一个数可以随意取。假使目前取得 aj,下一个数取ak(k>j),则ak必须满足gcd(aj,ak)≥L。 到底要取多少个数呢?自然是越多越好!
不用多说,这不仅是给lqp的难题,也是给你的难题。
输入
第一行包含两个数N 和 L.
接下来一行,有 N 个数用空格隔开,依次是 a1,a2…an.
输出
仅包含一行一个数,表示按上述取法,最多可以取的数的个数。
样例输入
5 6
7 16 9 24 6
样例输出
3
提示
选取 3个数16、24、6。gcd(16,24)=8,gcd(24,6)=6。
2≤L≤ai≤1 000 000;
题目来源
JSOI2010
// AC 77MS #include<iostream> #define MAX_AI 1000001 //a[i]的最大值 #define MAX_N 50001 //数组A的最大长度,取1000的话会WA1 #define MAX_PRIME 1001 //处理的最大素数,可能会不够,不够的话再改吧 #define MAX_DIVISOR 1001 //约数最多个数 int N,L; int a[MAX_N]; bool isPrime[MAX_PRIME]; //表示是否为素数 int primeNo; //素数表的大小 int prime[MAX_PRIME]; //素数表 int primeFactorNo; //某个a[i]的素因子表的大小 int primeFactor[MAX_N]; //某个a[i]的素因子表 int primeFactorN[MAX_N]; //某个a[i]每个素因子的幂 int divisorNo; //某个a[i]的约数表的大小 int divisor[MAX_N]; //某个a[i]的约数表 char maxLen[MAX_AI]; //maxLen[k] 表示最后一个最大公约数为 k 的话,可以连成的最长队列是多少 void makePrimeTable(){ int i,j; isPrime[2] = 1; for(i=3;i<MAX_PRIME;i+=2){ isPrime[i] = 1; } for(i=3;i<MAX_PRIME;i+=2){ if(isPrime[i]){ for(j=(i<<1);j<MAX_PRIME;j+=i){ isPrime[j] = 0; } } } for(primeNo=0,i=2;i<MAX_PRIME;i++){ if(isPrime[i]){ prime[++primeNo] = i; } } } // 将 k 拆分成素因子乘积的形式,存放于primeFactor[] 和primeFactorN[]中 void split(int k){ int i; primeFactorNo = 0; for(i=1;i<primeNo && prime[i]<=k; i++){ if(0==k%prime[i]){ primeFactor[++primeFactorNo] = prime[i]; primeFactorN[primeFactorNo] = 0; while(0==k%prime[i]){ primeFactorN[primeFactorNo]++; k /= prime[i]; } } } if(k!=1){ primeFactor[++primeFactorNo] = k; //最后一个存的可能不是素数 primeFactorN[primeFactorNo] = 1; } } void dfs(int index, int Number){ if(index>primeFactorNo){ divisor[++divisorNo] = Number; return; } int i; dfs(index+1,Number); for(i=1;i<=primeFactorN[index];i++){ Number *= primeFactor[index]; dfs(index+1,Number); } } // 利用 primeFactor[]数组和primeFactorN[primeFactorNo] 制作约数表 void makeDivisorTable(){ divisorNo = 0; dfs(1,1); } int refleshMaxLen(){ int i,len=0; //len记录用当前数字的约数作为最后一组公约数的最大长度 for(i=1;i<=divisorNo;i++){ if(divisor[i]>=L && maxLen[divisor[i]]>len){ len = maxLen[divisor[i]]; } } len++; //有了当前分析的这个数字之后,长度增加一 for(i=1;i<=divisorNo;i++){ if(divisor[i]>=L){ maxLen[divisor[i]] = len; } } return len; } int main(){ // freopen("test.txt","r",stdin); int i,j,maxLength=0; makePrimeTable(); scanf("%d%d",&N,&L); for(i=1;i<=N;i++){ scanf("%d",a+i); } for(i=1;i<=N;i++){ split(a[i]); makeDivisorTable(); j = refleshMaxLen(); if(maxLength<j){ maxLength = j; } } printf("%d\n",maxLength); }
相关文章推荐
- 南邮 OJ 1401 乘车费用
- [转]构建C协程之setjmp/long_jmp篇
- HDU 5351 MZL's Border(规律)
- RTEMS-BBB(四):rki镜像
- c++中的explicit关键字
- 防止Block的循环引用
- UIView的图层关系
- 孙源面试题试解(更新完毕)
- android_移植memtester
- 低级绕过手段
- Pie(poj 3122)二分法
- 64bit需要做的改变
- linux命令--------------top
- 如何在Android开发中让你的代码更有效率
- 栈的应用 - 波兰式与逆波兰式
- Wireshark远程抓包
- C#中的异常处理
- php 反射
- Cocos2d-x 3.6 命令行创建项目
- hdu 5351 MZL's Border (大数)