HGOI 20190310 题解
Posted ljc20020730
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HGOI 20190310 题解相关的知识,希望对你有一定的参考价值。
/* 又是又双叒叕WA的一天... 我太弱鸡了... 今天上午打了4道CF */
Problem 1 meaning
给出q组询问,求下列函数的值$ f(a) = maxlimits_{0 < b < a} { gcd(aoplus b,a & b)} $
对于100%的数据 $qleq 1000, 2 leq a_i leq 2^{25}-1$
结论题,直接打表找结论,发现当$a in [2^{n-1},2^{n}-2] (n geq 2)$ 答案为$2^{n} - 1$
当$a = 2^n - 1 ,n geq 1$时答案为a除自己外最大的约数。
直接打表处理26个特殊情况,实际程序复杂度$ O(q) $
# include <bits/stdc++.h> using namespace std; int a[27],Pow[27]; int fun(int x) { if (x==0) return 0; for (int i=1;i<=26;i++) if (x==Pow[i]-1) return a[i]; int i; for (i=1;i<=26;i++) if (x<=Pow[i]-2) break; return Pow[i]-1; } int main() { a[1]=0; a[2]=1; a[3]=1; a[4]=5; a[5]=1; a[6]=21; a[7]=1; a[8]=85; a[9]=73; a[10]=341; a[11]=89; a[12]=1365; a[13]=1; a[14]=5461; a[15]=4681; a[16]=21845; a[17]=1; a[18]=87381;a[19]=1; a[20]=349525; a[21]=299593; a[22]=1398101; a[23]=178481; a[24]=5592405; a[25]=1082401; a[26]=22369621; int n ;scanf("%d",&n); Pow[0]=1; for (int i=1;i<=26;i++) Pow[i]=Pow[i-1]*2; int ans; while(n--) { int x;scanf("%d",&x); printf("%d ",fun(x)); } return 0; }
Problem 2 Jongmah
给出n个数字在[1,m]内,构成若干个合法三元组,合法的定义是三元组内元素相同或连续。
对于100%的数据,$ n,mleq 10^6 $
考虑一个dp,先记录每个数出现几次,作为cnt[]数组
考虑若连续三元组超过2个,那么就可以转化为3个相同的三元组,所以在计算中,连续三元组最多为2个。
其他的就被计算在不连续的三元组内。
f[i][k][l]值小于i的所有数,三元组(i,i+1,i+2)选取k$kin [0,2]$,三元组(i-1,i,i+1)选取l个$l in [0,2]$ 最多合法三元组个数。
考虑从f[i-1][l][j]转移过来,枚举 j $ in [0,2]$,转移。
当前状态和前继状态比较在原来基础上多出来k个连续三元组(i,i+1,i+2),到此为止,已经用去
数 i-1 消耗 l+j 个; 数 i-2 消耗 j 个 ; 数 i 消耗 k+j+l个 ; 数 i+1 消耗 k+l ;数 i+2 消耗k个。
$ f[i-1][l][j] + k + left lfloor frac{cnt[i] - k - j - l}{3} ight floor $
初始化全是0
# include<bits/stdc++.h> # define fp(i,s,t) for(int i=s;i<=t;i++) using namespace std; const int N=1e6+10; int f[N][4][4],cnt[N]; int n,m; int main() { scanf("%d%d",&n,&m); int t; fp(i,1,n) scanf("%d",&t),cnt[t]++; int ans=0; fp(i,1,m) fp(k,0,2) fp(l,0,2) fp(j,0,2) { if(k+j+l>cnt[i]) continue; if(l+j>cnt[i-1]) continue; if(j>cnt[i-2]) continue; if(k+l>cnt[i+1]) continue; if(k>cnt[i+2]) continue; f[i][k][l]=max(f[i][k][l],f[i-1][l][j]+k+(cnt[i]-k-j-l)/3); ans=max(ans,f[i][k][l]); } cout<<ans<<‘ ‘; return 0; }
以上是关于HGOI 20190310 题解的主要内容,如果未能解决你的问题,请参考以下文章