任意区间GCD数

#include<bits/stdc++.h>
#define pi acos(-1.0)
using namespace std;
typedef long long ll;
const int maxn=5e5+30;
vector<ll>dp,pd;
unordered_map<ll,int>mp;//作用同MAP,但是底层是用HASH
int main(){
    int n;
    ll x;
    cin>>n>>x;//读入数组长及第一个数
    dp.push_back(x);//压入第一个数,注意是DP
    ++mp[x];//键值为X对应的值变为1,首先该数自身就可以表示一个GCD值
    cout<<x<<endl;
    for(int i=2;i<=n;++i){
        cin>>x;
        pd.push_back(x);//读入压入当前最新的数到PD,PD每次都更新,现在仅一个数
        ++mp[x];//对应键值继续加1
        cout<<x<<endl;
        ll tmp=x;//把当前输入的最新值为为临时值
        for(int j=0;j<dp.size();++j){//把当前的DP表扫一次,注意当前最新读的数没进DP
            x=__gcd(x,dp[j]);//把X赋为其与DP表中第J个数的GCD,此函数可以直接求GCD
            if(x!=tmp){//如果X变小了,就把X赋给TMP,MP该值+1,PD押入X
                tmp=x;
                ++mp[x];
                cout<<x<<endl;
                pd.push_back(x);
            }
        }
        swap(dp,pd);//把PD赋给DP,然后自清空
        pd.clear();
    }
    printf("%d\n",mp.size());//最后MP有多少个不同的键值,亦即不同GCD,就是答案
	return 0;
}
模拟过程:
DP读入第一个数,记入MP
PD读入第二个数,记入MP,然后与DP的数比较,如果有变小,又记入MP(表明出现了GCD,当然不排除之前出现过),就把变小的值压入PD
PD与DP交换,然后PD清空,每次都只用于最新值输入的比较,而DP是记录了逆序离当前输入的有效GCD比较值
注:代码中的cout<<x<<endl;可以明显地看出押入MP的顺序
Sample Input 1 4 9 6 2 4 6    Sample Output  6
6 4 9 6 2 4 6
----insert---1 4
dp 4
pd
----insert---2 9
1
now is 2
dp 4
pd 9 1
----insert---3 6
3
1
now is 3
dp 9 1
pd 6 3 1
----insert---4 2
1
now is 4
dp 6 3 1
pd 2 1
----insert---5 4
2
1
now is 5
dp 2 1
pd 4 2 1
----insert---6 6
2
1
now is 6
dp 4 2 1
pd 6 2 1
6

#include<bits/stdc++.h>
#define pi acos(-1.0)
using namespace std;
typedef long long ll;
const int maxn=5e5+30;
vector<ll>dp,pd;
map<ll,int> mp;//作用同MAP,但是底层是用HASH
int main(){
    int n;
    ll x;
    cin>>n>>x;//读入数组长及第一个数
    dp.push_back(x);//压入第一个数,注意是DP
    ++mp[x];//键值为X对应的值变为1,首先该数自身就可以表示一个GCD值
    cout<<"----insert---"<<1<<' '<<x<<endl;
    cout<<"dp ";for(int kk=0;kk<dp.size();kk++)cout<<dp[kk]<<' ';cout<<endl;
    cout<<"pd ";for(int kk=0;kk<pd.size();kk++)cout<<pd[kk]<<' ';cout<<endl;

    for(int i=2;i<=n;++i){
        cin>>x;
        pd.push_back(x);//读入压入当前最新的数到PD,PD每次都更新,现在仅一个数
        ++mp[x];//对应键值继续加1
        cout<<"----insert---"<<i<<' '<<x<<endl;
        ll tmp=x;//把当前输入的最新值为为临时值
        for(int j=0;j<dp.size();++j){//把当前的DP表扫一次,注意当前最新读的数没进DP
            x=__gcd(x,dp[j]);//把X赋为其与DP表中第J个数的GCD,此函数可以直接求GCD
            if(x!=tmp){//如果X变小了,就把X赋给TMP,MP该值+1,PD押入X
                tmp=x;
                ++mp[x];
                cout<<x<<endl;
                pd.push_back(x);
            }
        }
        cout<<"now is "<<i<<endl;
        cout<<"dp ";for(int kk=0;kk<dp.size();kk++)cout<<dp[kk]<<' ';cout<<endl;
        cout<<"pd ";for(int kk=0;kk<pd.size();kk++)cout<<pd[kk]<<' ';cout<<endl;


        swap(dp,pd);//把PD赋给DP,然后自清空
        pd.clear();
    }
    printf("%d\n",mp.size());//最后MP有多少个不同的键值,亦即不同GCD,就是答案
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值