Contest_5 0614 By lhq
来源:互联网 发布:java中如何记录日志 编辑:程序博客网 时间:2024/06/06 03:15
转载请注明出处:http://blog.csdn.net/lhq_er/article/details/73604681
题目来源:学军中学NOIP2013提高组原创模拟题day2
https://wenku.baidu.com/view/3d053c4c76eeaeaad0f3309d.html###
Solution
T1 完全平方数 关键字:欧拉筛,快速幂,贪心
这道题目有两个区分点: 1.筛选素数的方法 2.计算结果的方法
1.处理方法显然就是欧拉筛(线性筛)了,注意要筛选到n/2,到sqrt(n)是不够的。
2.我们对任意一个数的阶乘进行质因数分解,例如:
15!=
那么对于这些质因子我们能够取到的理论上的最大的完全平方数是
Tip:1.在求完质数后求n!中有几个质数p时可以用数学方法快速计算:
num=(n/p)+(n/
2.计算时要用到快速幂
3.一般的筛选法写得巧妙一点也可以过,如下:
//一般筛选法; int main(){ scanf("%lld",&n); memset(vis,false,sizeof(vis)); vis[1]=true; for (ll i=2;i<=n;i++) { if (!vis[i]) { prime[++tot]=i; for (ll j=i*i;j<=n;j+=i) vis[j]=true; } }
T2 卡片游戏 关键字:数学大力推一发,逆序对
上标解。
T3 围栏问题 关键字:搜索+剪枝,Dancing Links
这道题ZJOI2017讲课时提到过,可惜没有记住怎么做,当然记住了也没用,因为当时讲的是Dancing Links,其实对种种小数据可以搜索+剪枝水过
这道题目的关键是我们要推出下面这个性质:所有的围栏都是互不相交的矩形
————————————————————证明————————————————————
首先,两个围栏互相包含的情况不可能在最优解中出现(把里面那个拆掉可以节省篱笆,得到一个更优解)。
其次,两个围栏相交的情况也一定不是最优,如下图所示,把重叠的部分拆掉可以得到更优解。
由于我们的目标是最小化周长,可以得到这样一条重要性质:矩形的围栏比不规则形状的更优。如图,把里面的边往外平移,成为一个矩形的边框,这样可以在周长不变的情况下,围住更多的土地。(不用担心扩展出去的部分会和另外的围栏相交,因为这不可能在最优解中出现,刚才已经提到)
有些情况下,矩形边框不仅扩大围住的范围而且能节省周长。
所以,接下来我们只需考虑用矩形去包围兔子就够了。
定义基本矩形或叫极小矩形——假如这个矩形再往里缩小一点就会有兔子从里面逃出。
如就不是一个极小矩形,它可以往里收缩
现在它是一个极小矩形。
容易发现,最优解中必然只包含极小矩形。
——————————————————证毕————————————————————
解法一:
搜索+剪枝,枚举每一个兔子所在的栅栏,如果还可以再多一种栅栏就可以多一种选择:即开一个刚刚包围自己的栅栏。另一种选择就是和之前的某一个集合的兔子合并放到一个栅栏里,计算周长时找到上下左右的最大差值,记得+1。
解法二:
我们可以预处理出所有极小矩形:枚举所有兔子的非空子集,找出这个子集中最上、最左、最右、最下的兔子,就可得到一个极小矩形。(当然这样计算会出现许多重复的,剔除即可)。这种做法虽然是指数级的但是编码简单,而且n很小,仍可接受。
现在我们有了一堆矩形,对于每个矩形我们掌握它的两个属性:周长、围住了的兔子集合。问题转化为:从这堆矩形中选出不超过k个,在满足这些兔子集合互不相交,且其并集恰好是兔子全集的条件下,最小化总周长。
这是一个典型的精确覆盖问题,搜索解决即可。可以使用二进制来表示各个集合,用位运算的方法达到优化的效果。也可以用DLX来做,更快,更爽。 (我会告诉你我不会Dancing Links 吗,但不要慌,我会附上标程,可以借鉴一下)
总结:
这次考试T1没写出来欧拉筛,先优化版的一般筛法也没想到,只拿了70分,这提醒我要注意复习以前学过的知识,不要一直想着学新知识。T2也只拿了暴力分,数学推理都没敢去试一试,更没有想到是逆序对这种基础的知识,这也告诉了我们很多东西是伪装过的,不是你会逆序对就可以AC掉T2,还得有抽丝剥茧的能力。T3的dfs解法更是告诉了我们一样东西:暴力出奇迹。
CODE
T1
#include<bits/stdc++.h>using namespace std;#define ll long long#define MOD 100000007const ll MAXN=5000010,MAX_PRIME=350000;ll n,ans=1,tot;ll prime[MAX_PRIME];bool vis[MAXN];ll power(ll a,ll b,ll p){ ll ans=1; while (b) { if (b&1) ans=(ans*a)%p; a=(a*a)%p; b>>=1; } return ans;}//欧拉筛; int main(){ scanf("%lld",&n); memset(vis,false,sizeof(vis)); vis[1]=true; for (ll i=2;i<=n;i++) { if (!vis[i]) prime[++tot]=i; for (ll j=1;j<=tot && i*prime[j]<=n;j++) { vis[i*prime[j]]=true; if (i%prime[j]==0) break; } } for (ll i=1;i<=tot;i++) { ll t=n,a=prime[i],cnt=0; while (t>0) t/=a,cnt+=t; if (cnt>1) if (cnt&1) ans=(ans*power(a,cnt-1,MOD))%MOD; else ans=(ans*power(a,cnt,MOD))%MOD; } cout<<ans; return 0;}
T2
#include<bits/stdc++.h>using namespace std;#define ll long longconst ll MAXN=500010;ll tmp[MAXN],A[MAXN],B[MAXN],ans;ll gcd(ll a,ll b){ if (b==0) return a; else return gcd(b,a%b);}void Reverse_pair1(ll a[],ll b[],ll l,ll r){ if (l==r) return; ll mid=(l+r)>>1; Reverse_pair1(a,b,l,mid); Reverse_pair1(a,b,mid+1,r); ll i=l,j=mid+1,k=l; while (i<=mid && j<=r) if (a[i]<a[j]) b[k++]=a[i++]; else b[k++]=a[j++],ans+=mid-i+1; while (i<=mid) b[k++]=a[i++]; while (j<=r) b[k++]=a[j++]; for (ll i=l;i<=r;i++) a[i]=b[i];}void Reverse_pair2(ll a[],ll b[],ll l,ll r){ if (l==r) return; ll mid=(l+r)>>1; Reverse_pair2(a,b,l,mid); Reverse_pair2(a,b,mid+1,r); ll i=l,j=mid+1,k=l; while (i<=mid && j<=r) if (a[i]<=a[j]) b[k++]=a[i++]; else b[k++]=a[j++],ans-=mid-i+1; while (i<=mid) b[k++]=a[i++]; while (j<=r) b[k++]=a[j++]; for (ll i=l;i<=r;i++) a[i]=b[i];}int main(){ ll n,l,r,x,sum=0; scanf("%lld%lld%lld",&n,&l,&r); for (ll i=1;i<=n;i++) { scanf("%lld",&x); sum=sum+x; A[i]=l*i-sum; B[i]=r*i-sum; } Reverse_pair1(A,tmp,0,n); Reverse_pair2(B,tmp,0,n); ll tot=n*(n+1)/2; ll d=gcd(tot,ans); if (ans==tot) cout<<"1"; else cout<<ans/d<<"/"<<tot/d; return 0;}
T3
#include<bits/stdc++.h>using namespace std;#define ll long longconst int MAXN=16+1;int x[MAXN],y[MAXN],lx[MAXN],rx[MAXN],ly[MAXN],ry[MAXN],ans,n,m,maxk;void dfs(int t,int use,int tot){ if (tot>ans) return; if (t>n) { ans=tot; return; } if (use<maxk) { lx[use+1]=rx[use+1]=x[t]; ly[use+1]=ry[use+1]=y[t]; dfs(t+1,use+1,tot+4); lx[use+1]=ly[use+1]=rx[use+1]=ry[use+1]=0; } for (int i=1;i<=use;i++) { int minx=lx[i],miny=ly[i],maxx=rx[i],maxy=ry[i]; int c=tot-2*((maxx-minx+1+maxy-miny+1)); lx[i]=min(lx[i],x[t]); rx[i]=max(rx[i],x[t]); ly[i]=min(ly[i],y[t]); ry[i]=max(ry[i],y[t]); c+=2*((rx[i]-lx[i]+1+ry[i]-ly[i]+1)); dfs(t+1,use,c); lx[i]=minx; rx[i]=maxx; ly[i]=miny; ry[i]=maxy; }}int main(){ scanf("%d%d%d",&m,&maxk,&n); for (int i=1;i<=n;i++) scanf("%d%d",&x[i],&y[i]); ans=1<<30; dfs(1,0,0); cout<<ans; return 0;}
T3 Dancing Links
#include<iostream>#include<cstdio>#include<algorithm>#include<cstring>#include<cstdlib>using namespace std;int m=0,n;int l,kmax;int X[25],Y[25],totX=0,totY=0;//离散化;int x[25],y[25];int L[500000],R[500000],U[500000],D[500000],C[500000];int head;int S[25]={0};int W[500000];int arr[500000]={0};int ans=30000;void remove(const int c) { int i,j; L[R[c]] = L[c]; R[L[c]] = R[c]; for (i = D[c]; i != c; i = D[i]) { for (j = R[i]; j != i; j = R[j]) { U[D[j]] = U[j]; D[U[j]] = D[j]; S[C[j]]--; } }}void resume(const int c) { int i,j; for (i = U[c]; i != c; i = U[i]) { for (j = L[i]; j != i; j = L[j]) { S[C[j]]++; U[D[j]] = j; D[U[j]] = j; } } L[R[c]] = c; R[L[c]] = c; }void dfs(int k,int sum) { int i,j,t; int s=30000, c; if(sum>=ans)return; if (R[head] == head) { ans=sum; return; } if(k>=kmax)return; for (t = R[head]; t != head; t = R[t]) { if (S[t] < s) { s = S[t]; c = t; } } remove(c); for (i = D[c]; i != c; i = D[i]) { for (j = R[i]; j != i; j = R[j]) remove(C[j]); dfs(k + 1,sum+W[i/n]); for (j = L[i]; j != i; j = L[j]) resume(C[j]); } resume(c); return;}int main(){ scanf("%d%d%d",&l,&kmax,&n); for (int i=0;i<n;i++) scanf("%d%d",&x[i],&y[i]); for (int i=1;i<1<<n;i++){ int l=5000,r=0,u=5000,d=0; for (int j=0;j<n;j++) if(i&(1<<j)){ u=min(u,x[j]); d=max(d,x[j]); l=min(l,y[j]); r=max(r,y[j]); } bool ok=true; for (int j=0;j<n && ok;j++) if(!(i&(1<<j)) && x[j]>=u && x[j]<=d && y[j]>=l && y[j]<=r)ok=false; if(!ok)continue; W[++m]=(d-u+r-l+2)*2; for (int j=0;j<n;j++) if(i&(1<<j))arr[m*n+j]=1; } ///////////////////////////////// head=(m+1)*n;L[head]=R[head]=head; L[0]=head;R[head]=0;R[n-1]=head;L[head]=n-1; U[0]=D[0]=0; for (int j=1;j<n;j++){ L[j]=j-1; R[j-1]=j; U[j]=D[j]=j; } for (int i=1;i<=m;i++){ int last=0; int first; for (int j=0;j<n;j++){ if (arr[i*n+j]){ if(last!=0){ L[i*n+j]=last; R[i*n+j]=first; R[last]=i*n+j; last=i*n+j; } else { first=last=i*n+j; L[first]=R[first]=first; } } } if(last)L[first]=last; } for (int j=0;j<n;j++){ int last=j; for (int i=1;i<=m;i++){ if(arr[i*n+j]){ U[i*n+j]=last; D[i*n+j]=j; D[last]=i*n+j; last=i*n+j; C[i*n+j]=j; S[j]++; } } U[j]=last; } dfs(0,0);//DLX printf("%d\n",ans); return 0;}
- Contest_5 0614 By lhq
- Contest_5 0616 By lhq
- Contest_5 0612 By lhq
- Contest_6 0619 By lhq
- by
- group by order by
- group by + order by
- hive order by,sort by,distributed by
- group by
- Published by
- connect by
- by now
- connect by ~~~~
- group by
- by x_tr
- order by
- group by
- group by
- JDBC
- ASM AMDU工具使用
- 半路出家, 我的iOS自学之路-2-头文件, 属性, 引用计数, 协议, 类别, 类扩展
- async异步问题(waterfall、parallel、eachSeries、map、whilst)
- cglib动态代理实现
- Contest_5 0614 By lhq
- gulp-删除文件和文件夹
- 基本数据类型
- LSMW批处理使用方法(08)_步骤8、9
- cocos2d-x 3.0rc0 lua练习最基础例子
- mysql数据库迁移出错后新建数据库表django
- 2PC到3PC到Paxos到Raft到ISR
- 在 <stdint.h> 中定义的 uint8_t 其实为 unsigned char
- centos 6 安装pip