训练日志3 (7.14)
T1 序列
确实是一个被忽略的知识点,质因数分解(好像是高中数学知识)。
由于题目中要求的必须要相邻元素,搞得这道题简单了一点,因此我们只需要判断相邻三位的公比是否一样就好了。
首先特判公比为1的情况,该情况最简单,直接线性dp,找最长公共子串,记录ans。
然后我们可以每次以两个连续的数作为开头,以他们的公比为公共公比依次往下搜,相邻两个数的公比确定,所以不用考虑会有漏判的情况。
还有就是其中用到了STL set,一个高端的玩意,用到的功能就是判重(相同的元素添加不会改变set的大小),遇到重复开始暴力前搜,跳回到上一个出现该元素,再一次向下循环。
下面就是求公比,也就是用到了质因数分解。
对于每一个数x,我们都可以将它分解成p1^q1*p2^q2……的形式,我们找到两个可以整除的数,他们求商得到的会余掉多余部分而剩下相同元素,这些元素(素数)的指数gcd,在返回去求幂累乘,得到的便是最小公比。
gcd,快速幂是必须的,思路挺好理解,但是真要在考试的时候想确实不好想,没有想到质因数分解。
一定要注意 long long 的使用,define int long long,碰到大数据所有都要long long,爆了int会突变成0。
小弟不才。
1 #include<cstdio> 2 #include<cmath> 3 #include<cstring> 4 #include<iostream> 5 #include<algorithm> 6 #include<set> 7 #define HZOI using namespace std 8 HZOI; 9 const int L=1<<20|1; 10 char buffer[L],*S,*T; 11 #define getchar() ((S==T&&(T=(S=buffer)+fread(buffer,1,L,stdin),S==T))?EOF:*S++) 12 int n,ans; 13 int prime[170]={0,2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293,307,311,313,317,331,337,347,349,353,359,367,373,379,383,389,397,401,409,419,421,431,433,439,443,449,457,461,463,467,479,487,491,499,503,509,521,523,541,547,557,563,569,571,577,587,593,599,601,607,613,617,619,631,641,643,647,653,659,661,673,677,683,691,701,709,719,727,733,739,743,751,757,761,769,773,787,797,809,811,821,823,827,829,839,853,857,859,863,877,881,883,887,907,911,919,929,937,941,947,953,967,971,977,983,991,997,-1}; 14 int p[170],dp[100005]; 15 long long a[100005]; 16 int tot,qnow; 17 set<long long> s; 18 bool Check(register long long x,register int y) 19 { 20 if (x==1) return 1; 21 if (x<y or !y) return 0; 22 double wc1=log10(x),wc2=log10(y); 23 if ((wc1/wc2)-floor(wc1/wc2)>1e-11) return 0; 24 return 1; 25 } 26 long long FastPow(register long long x,register int q) 27 { 28 long long ans=1; 29 while (q) 30 { 31 if (q&1) ans*=x; 32 x*=x; 33 q>>=1; 34 } 35 return ans; 36 } 37 int GetGcd(register int x,register int y) 38 { 39 if(!y) 40 return x; 41 return GetGcd(y,x%y); 42 } 43 long long Judge(register long long x,register long long y) 44 { 45 int z=x/y; 46 int ooo[170],t=0,lh[170]; 47 for (register int i=1; i<=tot; ++i) 48 { 49 if (z%prime[i]) continue; 50 if (z<=1) break; 51 while (!(z%prime[i])) 52 { 53 ++p[i]; 54 z/=prime[i]; 55 } 56 ooo[++t]=p[i]; lh[t]=i; 57 p[i]=0; 58 } 59 if (z!=1) return 0; 60 int gcd=0; 61 for (register int i=1; i<=t; ++i) 62 if(!gcd) 63 gcd=ooo[i]; 64 else 65 gcd=GetGcd(gcd,ooo[i]); 66 long long ans=1; 67 for (register int i=1; i<=t; ++i) 68 ans*=FastPow(prime[lh[i]],(ooo[i]/gcd)); 69 return ans; 70 } 71 long long read() 72 { 73 register long long num=0;register char ch=getchar(); 74 while (ch<'0' or ch>'9') ch=getchar(); 75 while (ch>='0' and ch<='9') num=(num<<3)+(num<<1)+ch-48,ch=getchar(); 76 return num; 77 } 78 int main() 79 { 80 // freopen("1.in","r",stdin); 81 tot=10; 82 n=read(); 83 for (register int i=1; i<=n; ++i) 84 a[i]=read(); 85 int res=1; 86 ans=1; 87 for (register int i=2; i<=n; ++i) 88 { 89 if (!(a[i]^a[i-1])) res++; 90 else {ans=max(res,ans); res=1;} 91 } 92 ans=max(res,ans); 93 s.insert(a[1]); 94 res=1; 95 for (register int i=2; i<=n; ++i) 96 { 97 long long x=a[i-1],y=a[i]; 98 if (!(x^y)) {ans=max(res,ans);res=1;s.clear();s.insert(a[i]);qnow=0;continue;} 99 if (x<y) x^=y,y^=x,x^=y; 100 if (x%y) {ans=max(res,ans);res=1;s.clear();s.insert(a[i]);qnow=0;continue;} 101 int ss=s.size(); 102 s.insert(a[i]); 103 if (!(s.size()^ss)) 104 { 105 ans=max(res,ans); 106 while (a[i-1]!=y) 107 --i; 108 res=1; 109 s.clear(); 110 s.insert(a[i]); 111 continue; 112 } 113 if (!qnow) {qnow=Judge(x,y); ++res; ans=max(ans,res); continue;} 114 long long wc=x/y; 115 if (Check(wc,qnow)) {res++; ans=max(ans,res); continue;} 116 int qnow=Judge(x,y);res=1; s.clear(); s.insert(a[i-1]); 117 } 118 ans=max(ans,res); 119 printf("%d\n",ans); 120 return 0; 121 }
缘定,伴今生