A: http://codeforces.com/contest/1350/problem/A
题意:f(n)+n,求第k次的结果。f(n)为n的最小公因数。
解析:模拟一下,就可以看出,这是一个d=2的等差数列,第一项是f(n)+n,求第k项。所以先把f(n)求出来。
#include<iostream> #include<algorithm> using namespace std; int main() { int n , k ; int t; cin>>t; while(t--) { cin>>n>>k; int a1; for(int i=2;i<=n;i++) { if(n%i==0) { a1=i;break; } } a1+=n; cout<<a1+(k-1)*2<<endl; } }
B:http://codeforces.com/contest/1350/problem/B
题意:求最长递增序列。保证这个序列的相邻下标,后一个可以整除前一个。
解析:直接上最长递增序列的DP模板。但是要注意,第二层应该是for(int j=i+i;j<=n;j+=i),这样保证了相邻整除。比如i=1, j=2,3,4....更新了dp[2],那么用到dp[2]时,就需要dp[4]了。正好整除。
#include<iostream> #include<cstdio> #include<algorithm> #include<cmath> using namespace std; typedef long long ll; const int maxn=1e5+10; int dp[maxn]; ll a[maxn]; int main() { int t; cin>>t; while(t--) { int n; cin>>n; for(int i=1;i<=n;i++) { dp[i]=1; cin>>a[i]; } int maxx=1; for(int i=1;i<=n;i++) { for(int j=i+i;j<=n;j+=i) { if(a[i]<a[j]) { dp[j]=max(dp[j],dp[i]+1); maxx=max(maxx,dp[j]); } } } cout<<maxx<<endl; } }
C:http://codeforces.com/contest/1350/problem/C
题意:求gcd{lcm{a1,a2....an}}
解析:根据题目的规则,有:
gcd1=gcd{lcm(a1,a2),lcm(a1,a3),lcm(a1,a4)......lcm(a1,an)}
每一项lcm都有a1,那么a1*x=gcd1,x就是a2....an的最大公约数了,x和a1的最小公倍数,就是整体的最大公约数了,所以可以写成:
gcd1=lcm(a1,gcd(a2....an))
同理,gcd2=lcm(a2,gcd(a3...an))
总的gcd=gcd(gcd1,gcd2,gcd3.......)
所以可以先后缀预处理一下a1~an的gcd,然后再从i=1开始每次:ans=gcd(ans,lcm(ai,f[i+1]))就可以了。
#include<iostream> #include<cstdio> #include<algorithm> #include<cmath> using namespace std; typedef long long ll; const int maxn=2e5+10; ll s[maxn],a[maxn]; ll getlcm(ll x,ll y) { return x*y/__gcd(x,y); } int main() { int n ; cin>>n; for(int i=1;i<=n;i++) cin>>a[i]; for(int i=n;i>=1;i--) s[i]=__gcd(s[i+1],a[i]); ll ans=0; for(int i=1;i<=n;i++) { ans=__gcd(ans,getlcm(a[i],s[i+1])); } cout<<ans<<endl; }