zoukankan      html  css  js  c++  java
  • 【洛谷P1214】等差数列

    题目大意:列出从一个给定上界的双平方数集合中选出若干个数,组成长度为 N 的等差数列的首项和公差。

    题解:首先,因为是在双平方数集合上的等差数列,而且根据题目范围可知,上界不超过 2e5,可以先打表,将符合条件的双平方数存入一个数组,并排序离散化。在等差数列中,只要数列中的前两项确定,整个数列就会被确定下来。因此,考虑枚举序列的前两项,至此时间按复杂度为 (O(cnt^2))。接着,若直接枚举后面的项来判断是否长度可以到达 N 的话,时间复杂度还要多一个 cnt 的乘积因子,难以承受。其实,在枚举的过程中,产生了大量的无效结果,最后才判断导致时间复杂度暴增,同时根据双平方数集合不大,可以直接用桶来装,因此,可以直接枚举 N,每次判断数列的下一项是不是在双平方数集合中即可,时间复杂度为 (O(cnt^2*N))

    代码如下

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn=150000;
    
    int n,m,c[maxn],cnt;
    bool in[maxn];
    struct node{
    	int a,d;
    }ans[maxn];
    int tot;
    
    bool cmp(const node& x,const node& y){
    	if(x.d^y.d)return x.d<y.d;
    	return x.a<y.a;
    }
    
    void read_and_parse(){
    	scanf("%d%d",&n,&m);
    	for(int i=0;i<=m;i++)
    		for(int j=0;j<=m;j++)
    			c[++cnt]=i*i+j*j,in[c[cnt]]=1;
    	sort(c+1,c+cnt+1);
    	cnt=unique(c+1,c+cnt+1)-c-1;
    }
    
    void solve(){
    	for(int i=1;i<=cnt-n+1;i++)
    		for(int j=i+1;j<=cnt-n+2;j++){
    			int d=c[j]-c[i],len=2,now=c[j],flag=1;
    			if(c[i]+(n-1)*d>c[cnt])break;
    			while(len<n){
    				++len,now+=d;
    				if(!in[now]){flag=0;break;}
    			}
    			if(flag)ans[++tot]=node{c[i],d};
    		}
    	if(!tot)puts("NONE");
    	else{
    		sort(ans+1,ans+tot+1,cmp);
    		for(int i=1;i<=tot;i++)printf("%d %d
    ",ans[i].a,ans[i].d);
    	}
    }
    
    int main(){
    	read_and_parse();
    	solve();
    	return 0;
    } 
    
  • 相关阅读:
    分享一个小故事
    思维局限
    java程序员笑不死的经历ส้้้้้้้้้
    一些话
    定位 java虚拟机内存问题 个人总结
    关于分布式事务、两阶段提交协议、三阶提交协议(转)
    maven常用配置信息和常量
    Mybatis-常见SQL语句示例
    Redis主从同步原理-SYNC
    B+树在mysql数据库索引中的使用
  • 原文地址:https://www.cnblogs.com/wzj-xhjbk/p/10037026.html
Copyright © 2011-2022 走看看