2017 10 08 NOIP2017模拟赛
来源:互联网 发布:js float 保留两位小数 编辑:程序博客网 时间:2024/06/16 20:01
这次考的还不错哈
可惜第二题输入的数据忘开longlong了。。。只有80分
弹钢琴 1794
这题的情景描述还是比较坑的
其实讲的就是从n个数中取k个,将所有情况里的最大值加起来
只要排序一下(从小到大)
就可以发现每个数只要是和它前面的组合,这样它就是组合的最大值
用前缀和维护一下1~k的组合数量就可以了
不过这题用逆元结合下费马小定理也能直接算出来
删除数字 2988
又是一道状压DP
我们只需要计录一下当前行的数的状态
就可以转移了,当然,别忘了开longlong。。。
如果直接枚举上一层状态,再加上枚举当前状态,时间复杂度显然超了
其实可以发现在寻找上一层的状态的时候
只有那些小于或者等于当前状态的数是合法的
那么就可以将每一层可以生成的数都sort一遍
转移状态的时候二分查找一下就能在log的时间里找到
当然,这么做要将dp数组维护一下前缀和
#include<iostream>#include<cstdio>#include<algorithm>#include<cstring>using namespace std;#define FOR(i,a,b) for(int i=(a),i##_end_=(b);i<=i##_end_;++i)#define DOR(i,a,b) for(int i=(a),i##_end_=(b);i>=i##_end_;--i)#define INF 0x3f3f3f3f#define LL long long#define N 105#define P 1000000007void chkmx(int &a,int b){if(a<b)a=b;}void chkmi(int &a,int b){if(a>b)a=b;}int MAX(int a,int b){return a>b?a:b;}int MIN(int a,int b){return a<b?a:b;}int Num[N][1<<13],l[N];LL ans,dp[N][1<<13],A[N],Sum[N][1<<13];int n;void Init(){ FOR(i,0,n){ LL t=A[i]; while(t) Num[i][l[i]++]=t%10,t/=10; FOR(j,1,(1<<l[i])-1){ LL &sum=Sum[i][j],h=1; FOR(k,0,l[i]-1) if(j&(1<<k)) sum+=Num[i][k]*h,h*=10; } } FOR(i,0,n) sort(Sum[i]+1,Sum[i]+(1<<l[i]));}LL Find(int i,LL sum){ int L=0,R=(1<<l[i])-1,mid,tmp=0; while(L<=R){ mid=L+R>>1; if(Sum[i][mid]<=sum) tmp=mid,L=mid+1; else R=mid-1; } return dp[i][tmp];}int main(){// freopen("num.in","r",stdin);// freopen("num.out","w",stdout); cin>>A[0]>>n; FOR(i,1,n) A[i]=A[i-1]+1; Init(); FOR(i,1,(1<<l[0])-1) dp[0][i]=1+dp[0][i-1]; FOR(i,1,n) FOR(j,1,(1<<l[i])-1){ dp[i][j]=Find(i-1,Sum[i][j]); dp[i][j]=(dp[i][j]+dp[i][j-1])%P; } cout<<dp[n][(1<<l[n])-1]<<endl; return 0;}
其实还有一种方法效率更高
排完序后,可以利用类似归并排序的方法直接转移
这就能实现在线性时间内完成一行的状态转移
#include<iostream>#include<cstdio>#include<algorithm>#include<cstring>using namespace std;#define FOR(i,a,b) for(int i=(a),i##_end_=(b);i<=i##_end_;++i)#define DOR(i,a,b) for(int i=(a),i##_end_=(b);i>=i##_end_;--i)#define INF 0x3f3f3f3f#define LL long long#define N 105#define P 1000000007void chkmx(int &a,int b){if(a<b)a=b;}void chkmi(int &a,int b){if(a>b)a=b;}int MAX(int a,int b){return a>b?a:b;}int MIN(int a,int b){return a<b?a:b;}int Num[N][1<<13],l[N];LL ans,dp[N][1<<13],A[N],Sum[N][1<<13];int n;void Init(){ FOR(i,0,n){ LL t=A[i]; while(t) Num[i][l[i]++]=t%10,t/=10; FOR(j,1,(1<<l[i])-1){ LL &sum=Sum[i][j],h=1; FOR(k,0,l[i]-1) if(j&(1<<k)) sum+=Num[i][k]*h,h*=10; } } FOR(i,0,n) sort(Sum[i]+1,Sum[i]+(1<<l[i]));}void Add(LL &a,LL b){ a=(a+b)%P;}void Merge(int i){ int s=1; FOR(j,1,(1<<l[i])-1){ dp[i][j]=dp[i][j-1]; while(s<(1<<l[i-1])&&Sum[i][j]>=Sum[i-1][s]) Add(dp[i][j],dp[i-1][s++]); }}int main(){// freopen("num.in","r",stdin);// freopen("num.out","w",stdout); cin>>A[0]>>n; FOR(i,1,n) A[i]=A[i-1]+1; Init(); FOR(i,1,(1<<l[0])-1) dp[0][i]=1; FOR(i,1,n) Merge(i); FOR(i,1,(1<<l[n])-1) Add(ans,dp[n][i]); cout<<ans<<endl; return 0;}
本题也可以滚动数组,但显然没必要
四点旅行 2989
这题其实不怎么难
按照题意模拟下来我们可以发现复杂度都堆在找最短路上
其实可以发现这道题的边权都是1
那么,直接bfs就好了
#include<iostream>#include<cstdio>#include<algorithm>#include<cstring>#include<queue>using namespace std;#define FOR(i,a,b) for(int i=(a),i##_end_=(b);i<=i##_end_;++i)#define DOR(i,a,b) for(int i=(a),i##_end_=(b);i>=i##_end_;--i)#define INF 0x3f3f3f3f#define LL long long#define M 2005#define N 5005#define P 1000000007void chkmx(int &a,int b){if(a<b)a=b;}void chkmi(int &a,int b){if(a>b)a=b;}int MAX(int a,int b){return a>b?a:b;}int MIN(int a,int b){return a<b?a:b;}int d[M][M];struct node{int maxl[2],s[2],cnt[2];}A[M];vector<int>es[N];struct W {int x,v;};int n,m,ans;queue<W> Q;void bfs(int s){ Q.push((W){s,0}); while(!Q.empty()){ W q=Q.front();Q.pop(); int x=q.x; if(d[s][x]!=INF) continue; d[s][x]=q.v; FOR(i,0,es[x].size()-1){ int y=es[x][i]; if(d[s][y]!=INF) continue; Q.push((W){y,q.v+1}); } }}int main(){// freopen("four.in","r",stdin);// freopen("four.out","w",stdout); memset(d,INF,sizeof(d)); cin>>n>>m; FOR(i,1,m){ int a,b; scanf("%d%d",&a,&b); es[a].push_back(b); } FOR(i,1,n) bfs(i); FOR(i,1,n)FOR(j,1,n){ if(d[i][j]==INF||i==j)continue; if(d[i][j]>A[i].maxl[0]) A[i].s[0]=j,A[i].cnt[0]=1,A[i].maxl[0]=d[i][j]; else if(d[i][j]==A[i].maxl[0]) A[i].cnt[0]++; if(d[i][j]>A[j].maxl[1]) A[j].s[1]=i,A[j].cnt[1]=1,A[j].maxl[1]=d[i][j]; else if(d[i][j]==A[j].maxl[1]) A[j].cnt[1]++; } FOR(i,1,n)FOR(j,1,n){ if(d[i][j]==INF||!A[i].cnt[1]||!A[j].cnt[0]||i==j)continue; if(A[i].s[0]==A[j].s[1]&&A[i].cnt[0]==1&&A[j].cnt[1]==1) continue; chkmx(ans,A[i].maxl[1]+d[i][j]+A[j].maxl[0]); } cout<<ans<<endl; return 0; }
阅读全文
1 0
- 2017 10 08 NOIP2017模拟赛
- 2017 10 03 NOIP2017模拟赛
- 2017 10 06 NOIP2017模拟赛
- 2017 10 07 NOIP2017模拟赛
- 2017 10 09 NOIP2017模拟赛
- NOIP2017模拟赛(10) 总结
- NOIP2017模拟赛1
- NOIP2017模拟赛8
- NOIP2017模拟赛9
- NOIP2017模拟赛(1) 总结
- NOIP2017模拟赛(2) 总结
- NOIP2017模拟赛(3) 总结
- NOIP2017模拟赛(4) 总结
- NOIP2017模拟赛(5) 总结
- NOIP2017模拟赛(6) 总结
- NOIP2017模拟赛(7) 总结
- NOIP2017模拟赛(8) 总结
- NOIP2017模拟赛(9) 总结
- lua脚本学习8
- Asp.net Core 2.0+EntityFrameWorkCore 2.0添加数据迁移
- Codeforces Round #439 (Div.2)
- 线性表
- MOOS例程HelloWorld-详细注释
- 2017 10 08 NOIP2017模拟赛
- 数据结构顺序表实现
- 10个重要的Linux ps命令实战
- lua脚本学习9
- 内部类反序列化问题(fastjson exception: create instance error)
- 使用VS Code编译运行C/C++程序
- 在CentOS7上安装MongoDB
- 3. Spring Boot 初步了解
- Poj 2970 The lazy programmer(贪心)