qduoj 153 cfenglv的一道简单签到题 (二分+分解因子)
来源:互联网 发布:劳动法教材推荐 知乎 编辑:程序博客网 时间:2024/05/22 06:19
cfenglv的一道简单签到题
发布时间: 2017年6月11日 17:59 最后更新: 2017年6月11日 18:11 时间限制: 4000ms 内存限制: 128M
据说,julyc决定给学弟学妹出一场月赛,于是他脑中浮现了许多很棒棒的出题创意。
而cfenglv恰巧在机房,于是他把一道题的创意说给了cfenglv听:
求区间gcd(最大公约数)大于等于k的最大区间长度len
这个问题cfenglv思考了一下,发现可以做,但是又不想做,于是提议放到月赛上给其他人做,julyc表示同意。
那么,你能把这个这么棒棒的问题给解决吗?
第一行一个整数t代表数据组数
接下来每组数据
第一行输入两个整数n,k
0<n,k<=1e5
接下来n个正整数
保证所有数据不大于1e5
每组数据输出一行,并输出ans
复制
15 33 6 9 2 5
3
#include <algorithm>#include <iostream>#include <cstring>#include <cstdio>#include <vector>#include <cmath>using namespace std;const int maxn = 1e5 + 5;vector<int> fac[maxn];int a[maxn], cnt[maxn], t, n, k;int check(int x) //这里比较巧妙, 先从头找长度x个,然后不断向左移动, 移动时候 就先把第一个的因子删掉,加上新的这个因子就好了。。两个for{ for(int i = 1; i <= x; i++) { for(int j = 0; j < fac[i].size(); j++) { cnt[fac[i][j]]++; if(cnt[fac[i][j]] >= x && fac[i][j] >= k) return 1; } } for(int i = x+1; i <= n; i++) { int tem = i-x; for(int j = 0; j < fac[tem].size(); j++) cnt[fac[tem][j]]--; for(int j = 0; j < fac[i].size(); j++) { cnt[fac[i][j]]++; if(cnt[fac[i][j]] >= x && fac[i][j] >= k) return 1; } } return 0;}int main(){ cin >> t; while(t--) { for(int i = 1; i <= n; i++) fac[i].clear(); scanf("%d%d", &n, &k); for(int i = 1; i <= n; i++) scanf("%d", &a[i]); for(int i = 1; i <= n; i++) { for(int j = 1; j <= sqrt(a[i]); j++) { if(a[i]%j) continue; fac[i].push_back(j); if(a[i]/j != j) fac[i].push_back(a[i]/j); } } int l = 1, r = n, mid, ans = 0; while(l <= r) { mid = (l+r)/2; if(check(mid)) ans = mid, l = mid + 1; r = mid - 1; } printf("%d\n", ans); } return 0;}
一共 就1e5 ,可以把1-1e5所有的的数的因子都找出来, 那样就不用每次都打表了 标程代码:
#include<bits/stdc++.h>using namespace std;const int maxn=100005;vector<int>g[maxn];int num[maxn],a[maxn];void get_div(int n) {for(int i=1;i*i<=n;i++){if(n%i==0){if(n/i!=i)g[n].push_back(n/i);g[n].push_back(i);}}}void init() //把所有的数的因子都弄出来{for(int i=1;i<=1e5;i++)get_div(i);}int check(int len,int k,int n){memset(num,0,sizeof(num));for(int i=1;i<=len;i++){for(int j=0;j<g[a[i]].size();j++){if(g[a[i]][j]<k)continue;num[g[a[i]][j]]++;if(num[g[a[i]][j]]==len)return 1;}}for(int i=len+1;i<=n;i++){for(int j=0;j<g[a[i-len]].size();j++){if(g[a[i-len]][j]<k)continue;num[g[a[i-len]][j]]--;}for(int j=0;j<g[a[i]].size();j++){if(g[a[i]][j]<k)continue;num[g[a[i]][j]]++;if(num[g[a[i]][j]]==len)return 1;}}return 0;}int main(){int t;init();//freopen("1.in","r",stdin);//freopen("1.out","w",stdout);scanf("%d",&t);while(t--){int n,k;scanf("%d%d",&n,&k);for(int i=1;i<=n;i++)scanf("%d",&a[i]);int l=0,r=n+1;while(r-l>1){int mid=(l+r)/2;if(check(mid,k,n))l=mid;elser=mid;}//printf("test %d\n",a[100000-50]);printf("%d\n",l);}return 0;}
阅读全文
2 0
- qduoj 153 cfenglv的一道简单签到题 (二分+分解因子)
- qduoj cfenglv的一道简单签到题(区间gcd rmq,二分)
- cfenglv的一道简单签到题 QDU
- qduoj 一道非常简单的签到题
- qduoj 96 一道非常简单的签到题
- qduoj no cer的一道简单签到题
- qduoj kkun的一道简单签到题(优先队列)
- qduoj 一道简单的数据结构题(水题)
- QDUOJ 蒸鱼的一个简单签到题 思维+kmp
- qduoj 102 一道非常简单的数学题(构造)
- qduoj 签到题 (树状数组)
- QDU BelamiYao的一道简单签到题(思维)
- qduoj 真-签到-炸老师的日记(贪心)
- qduoj 88 一道非常简单的炉石题(最大匹配)
- qduoj ycb老师与一道简单的物理题 三分
- QDUOJ 39 - 签到题(线段树)
- 周赛-一道签到题(kmp)
- 一道签到题
- Idea Plugin 开发
- eclipse html 格式化
- rsync使用说明
- @Transactional事务不起作用原因补充
- JAVA设计模式之工厂模式(简单工厂模式+工厂方法模式)
- qduoj 153 cfenglv的一道简单签到题 (二分+分解因子)
- 工厂模式
- 解决移动端可恨的滚动穿透问题
- c语言上机考试(二)
- Android ListView控件
- Linux进程通信之消息队列的双向通信
- keras的基本用法(五)——图像predict
- MySQl操作整理01
- 常用查找算法