http://acm.hdu.edu.cn/showproblem.php?pid=4961
先贴个O(nsqrtn)求1-n所有数的所有约数的代码:
vector<int>divs[MAXN]; void caldivs() { for(int i=1;i<MAXN;i++) for(int j=i;j<MAXN;j+=i) divs[j].push_back(i); }
有了这个当时理下思路就可写了,但是重复数处理注意:
1、用一个数组vis[] vis[i]=1表示i存在 或者pos[v]=j表示v在下标为j的位置 这种方法,虽然高效,但是如果出现重复的数,pos就只是更新到最近的一个数,而且vis只是记录了一个数,最好vis[i]++,如果删除一个数vis[i]--;
处理了重复数281ms AC
100000这个范围的数,即使多CASE,nsqrtn的算法还是可以一搞的
奇怪的是C++显示stack_overflow G++ AC 可是我没有递归啊,难道vector
#include <cstdio> #include <cstring> #include <algorithm> #include <string> #include <iostream> #include <iomanip> #include <cmath> #include <map> #include <set> #include <queue> using namespace std; #define ls(rt) rt*2 #define rs(rt) rt*2+1 #define ll long long #define ull unsigned long long #define rep(i,s,e) for(int i=s;i<e;i++) #define repe(i,s,e) for(int i=s;i<=e;i++) #define CL(a,b) memset(a,b,sizeof(a)) #define IN(s) freopen(s,"r",stdin) #define OUT(s) freopen(s,"w",stdout) const ll ll_INF = ((ull)(-1))>>1; const int MAXN = 1e5+10; const int INF = MAXN*13;/// int vis[MAXN]; int a[MAXN],b[MAXN],c[MAXN]; int maxm[MAXN],minm[MAXN],f[MAXN],g[MAXN],maxpos[MAXN],minpos[MAXN]; vector<int>divs[MAXN]; void caldivs() { for(int i=1;i<MAXN;i++) for(int j=i;j<MAXN;j+=i) divs[j].push_back(i); } int n; ll ans; int main() { //IN("1002.txt"); caldivs(); while(~scanf("%d",&n) && n) { vector<int>pos[MAXN]; CL(vis,0); for(int i=0;i<n;i++) { scanf("%d",&a[i]); vis[a[i]]++; pos[a[i]].push_back(i); maxm[i]=-INF;// minm[i]=INF;// } for(int i=0;i<n;i++) for(int j=0;j<divs[a[i]].size();j++) { int vv = divs[a[i]][j]; if(vis[vv]) { for(int k=0;k<pos[vv].size();k++) { if(i<pos[vv][k]) maxm[pos[vv][k]]=max(maxm[pos[vv][k]],i); if(i>pos[vv][k]) minm[pos[vv][k]]=min(minm[pos[vv][k]],i); } } } /*for(int i=0;i<n;i++) { for(int j=0;j<divs[a[i]].size();j++) { if(vis[divs[a[i]][j]] && maxpos[a[i]]<pos[divs[a[i]][j]]) { maxm[divs[a[i]][j]]=max( maxm[divs[a[i]][j]],maxpos[a[i]] ); } if(vis[divs[a[i]][j]] && minpos[a[i]]>pos[divs[a[i]][j]] ) { minm[divs[a[i]][j]]=min( minm[divs[a[i]][j]],minpos[a[i]] ); } //////////// //printf("%d %d ma=%d mi=%d \n",divs[a[i]][j],a[i],maxm[9],minm[9]); ///////////// } }*/ ans=0; for(int i=0;i<n;i++) { if(maxm[i]==-INF) { f[i]=maxm[i]=i;//maxm相当于f } else { f[i]=maxm[i]; } b[i]=a[f[i]]; if(minm[i]==INF) { g[i]=minm[i]=i;//minm相当于g } else { g[i]=minm[i]; } c[i]=a[g[i]]; ans+=(long long)b[i]*c[i]; } //////////////// /*for(int i=0;i<n;i++) { printf("###ma=%d mi=%d\n",f[i],g[i]); }*/ ////////////////// printf("%I64d\n",ans); } return 0; }
hdu 4961 数学杂题
时间: 2024-10-12 18:33:46