Time Limits: 1000 ms Memory Limits: 262144 KB
Description
我们给出一个长度为 n 的序列 a1,a2,...,an,对于每一个 ai我们需要找到一个 不等于 i 的最小的 j 使得 ai和 aj的距离是最小的。
Input
第一行一个整数 n。 接下来 n 行,第 i 行一个整数 ai。
Output
n 行,第 i 行一个整数,表示 d(ai,aj)最小时最小的 j。
Sample Input
6
1
2
3
4
5
6
Sample Output
2
1
1
2
1
2
Data Constraint
30%的数据,n<=1000。
另外 20%的数据,ai<=1000。
100%的数据,2<=n<=100000,1<=ai<=1000000。
显然,对于第i个数,他的答案是d[i] + d[j] - common(a[i],a[j])//d指质因数个数,common指共同质因数数目
至于d的处理可以用欧拉筛。
然后我们枚举约数,这意味着确定了common的值,然后维护最大和次大的d[],最大的d[]的那个数对应的答案用次大的更新,其余的用最大的更新。
时间复杂度O(sigma(Ai/p){0<p<=Ai})
不会超时
#include
#include
#include
#include
#include
using namespace std; const int N=1000100,INF=0x7fffffff,M=1000010; int pri[M],i,j,k,n,a[N],l[M],d[N],getm[M],ans[N],h[M]; bool p[M]; int main(){ cin>>n; int maz=0; memset(getm,67,sizeof(getm)); for(i=1;i<=n;i++){ scanf("%d",&a[i]); if(++h[a[i]]==2){ getm[a[i]]=0; ans[l[a[i]]]=i; } maz=max(a[i],maz); if(!l[a[i]])l[a[i]]=i;else{ ans[i]=l[a[i]]; } } int tt=0; d[1]=0; for(i=2;i<=maz;i++){ if(p[i]==0){ pri[++tt]=i; d[i]=1; } for(j=1;j<=tt;j++){ if(i*pri[j]>maz)break; d[i*pri[j]]=d[pri[j]]+d[i]; p[pri[j]*i]=1; if(i%pri[j]==0)break; } } int q[N];//getm i mean i can get how min times // q get a[i] // miz get min d[i] // u,v get min d[i]_num memset(q,0,sizeof(q)); for(i=1;i<=maz;i++){//欧拉筛 int miz=INF,se=INF,u,v,r=0; for(j=1;(k=j*i)<=maz;j++){ if(l[k]){ q[++r]=k; if(d[k]
d[q[j]]+miz-2*d[i]||(d[q[j]]+miz-2*d[i]==getm[q[j]]&&u
< code>
数的表示
Time Limits: 1000 ms Memory Limits: 262144 KB
Description
YJC 在学完了幂函数之后表示很兴奋,他总是在琢磨如何更好的用数的整数次幂来表示一个数,比如说16=24=22^2,于是他给每一种表示方法定义了一个价值:若一个数n被表示成a1^a2^…^an(ai>1,n>1),那么这个表示方法的价值就是n(如样例中写成16=2^2^2的价值就是3),现在现在 YJC 向你提出了一个问题:给了你若干个数,这些数以价值为 3 的表示形式给出,问有多少种不同的价值至少为 3 的表示方式。
Input
输入一个形如a^b^c的字符串和一个整数P,表示一个价值为 3 的表示方式。
Output
输出一行表示答案模P。
Sample Input
样例1
4^2^2 100
样例2
8^12^2 100
Sample Output
样例1
2
样例2
10
Data Constraint
对于 20%的数据,2 ≤ a, b, c ≤ 10。
对于 50%的数据,2 ≤ a, b, c ≤ 100。
对于 70%的数据,2 ≤ a, b, c ≤ 1000。
对于 100%的数据, 2 ≤ a, b, c ≤ 50000。
对于所有数据,P ≤ 109

#include
#include
#include
#include
#include
using namespace std; const int N=50010; int i,j,k,a,b,c,p; typedef int list[N][2]; list C,B; int f[N]; char ch[100]; int gcd(int a,int b){ if(b==0)return a ;else return gcd( b, a % b ); } int factorize(int n,list &fac){ int k=n,i=2,u=0; //memset(fac,0,sizeof(fac)); fac[0][0]=0;fac[0][1]=0; fac[1][0]=0;fac[1][1]=0; while(i<=floor(sqrt(k))){ if(k % i==0 ) { k/=i; if(fac[u][0]==i)++fac[u][1];else { ++fac[++u][1]; fac[u][0]=i; fac[u+1][0]=0;fac[u+1][1]=0; } } else ++i; } if(k!=1){ if(fac[u][0]==k)++fac[u][1];else { ++fac[++u][1]; fac[u][0]=k; fac[u+1][0]=0;fac[u+1][1]=0; } } int g=fac[1][1]; for(i=2;i<=u;i++){ g=gcd(fac[i][1],g); } return g; } list tem; void combine(list &A,list &B){ int l=1,r=1,k=0; while(A[l][0]!=0||B[r][0]!=0){ if(A[l][0]==B[r][0]){ tem[++k][1]=A[l][1]+B[r++][1]; tem[k][0]=A[l++][0]; }else if((A[l][0]==0||A[l][0]>B[r][0])&&B[r][0]!=0){ tem[++k][0]=B[r][0]; tem[k][1]=B[r++][1]; }else { tem[++k][0]=A[l][0]; tem[k][1]=A[l++][1]; } } for(int i=1;i<=k;i++)A[i][0]=tem[i][0],A[i][1]=tem[i][1]; } void process(int n){ int g=factorize(n,tem); int r=floor(sqrt(g)); for(int i=2;i<=r;i++){ if(g % i==0){ if(i!=g/i)f[n]+=f[i]+f[g/i];else f[n]+=f[i]; f[n]%=p; } } f[n]++; f[n]+=f[g]; } int main(){ scanf("%s%d",ch,&p); int len=strlen(ch); int po=1; for(i=0;i<=len-1;i++){ if(po==1&&ch[i]!='^'){ a=a*10+(int)ch[i]-48; }else if (po==2&&ch[i]!='^'){ b=b*10+(int)ch[i]-48; }else if (po==3&&ch[i]!='^'){ c=c*10+(int)ch[i]-48; }else ++po; } int g=factorize(a,C); factorize(g,C); factorize(b,B); for(i=1;B[i][0]!=0;i++)B[i][1]*=c; combine(C,B); int maxc=0; for(i=1;C[i][0]!=0;i++)maxc=max(C[i][1],maxc); long long ans=0; for(int w=2;w<=maxc;w++){ process(w); long long mlt=1; for(i=1;C[i][0]!=0;i++)mlt=(mlt*(C[i][1]/w+1))% p; mlt--; mlt=(mlt*f[w])%p; ans= ( ans + mlt ) % p; } cout<
总结::
数论题思路来的不容易,第一题告诉了我要对计算式研究仔细,比如说固定某个量其他的就好解决了
第二题要想到幂它的根,即Num=Pi(FACTORi^Ki) ,gcd(Ki)则是它的根