洛谷-P1414 又是毕业季II -枚举因子
P1414 又是毕业季II:https://www.luogu.org/problemnew/show/P1414
题意:
给定一个长度为n的数列。要求输出n个数字,每个数字代表从给定数列中最合理地取出 i 个数后的最大公约数。
思路:
枚举因子,复杂度为n*(sqrt(max)),若一个因子x出现了k次,那么说明从数列中取出 k 个数至少可以得到最大公约数x。
* 1、 求出每个因数出现的次数。
* 2、 对于每个次数记录最大的因数。
* 3、 根据f[k]=max(f[k],f[k+1])逆向递推。(如果已经知道k个数的最大公约数是m,那么l(l<k)个数的最大公约数一定大于等于m)。
#include <algorithm> #include <iterator> #include <iostream> #include <cstring> #include <cstdlib> #include <iomanip> #include <bitset> #include <cctype> #include <cstdio> #include <string> #include <vector> #include <stack> #include <cmath> #include <queue> #include <list> #include <map> #include <set> #include <cassert> using namespace std; //#pragma GCC optimize(3) //#pragma comment(linker, "/STACK:102400000,102400000") //c++ #define lson (l , mid , rt << 1) #define rson (mid + 1 , r , rt << 1 | 1) #define debug(x) cerr << #x << " = " << x << "\n"; #define pb push_back #define pq priority_queue typedef long long ll; typedef unsigned long long ull; typedef pair<ll ,ll > pll; typedef pair<int ,int > pii; typedef pair<int,pii> p3; //priority_queue<int> q;//这是一个大根堆q //priority_queue<int,vector<int>,greater<int> >q;//这是一个小根堆q #define fi first #define se second //#define endl '\n' #define OKC ios::sync_with_stdio(false);cin.tie(0) #define FT(A,B,C) for(int A=B;A <= C;++A) //用来压行 #define REP(i , j , k) for(int i = j ; i < k ; ++i) //priority_queue<int ,vector<int>, greater<int> >que; const ll mos = 0x7FFFFFFF; //2147483647 const ll nmos = 0x80000000; //-2147483648 const int inf = 0x3f3f3f3f; const ll inff = 0x3f3f3f3f3f3f3f3f; //18 const int mod = 1e9+7; const double esp = 1e-8; const double PI=acos(-1.0); template<typename T> inline T read(T&x){ x=0;int f=0;char ch=getchar(); while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar(); while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar(); return x=f?-x:x; } /*-----------------------showtime----------------------*/ const int maxn = 1e6+9; int cnt[maxn],f[maxn]; int ans[maxn],a[maxn]; int main(){ int n; scanf("%d", &n); for(int i=1; i<=n; i++)scanf("%d", &a[i]); for(int i=1; i<=n; i++){ int t = sqrt(a[i]); for(int j=1; j<=t; j++){ if(a[i] % j == 0){ cnt[j]++; if(a[i]/j != j)cnt[a[i]/j]++; } } } for(int i=1; i<maxn; i++) f[cnt[i]] = i; int mx = 0; for(int i=n; i>=1; i--){ ans[i] = max(f[i], mx); mx = max(mx,f[i]); } for(int i=1; i<=n; i++){ printf("%d\n", ans[i]); } return 0; }
skr