计蒜客 2017 NOIP 提高组模拟赛(二)Day2
来源:互联网 发布:网络信息工程师 编辑:程序博客网 时间:2024/05/16 07:08
T1:劫富济贫
这题一开始hash做的,超时
#include<cstdio>#include<cstdlib>#include<algorithm>#include<cstring>#include<map>#include<set>#define MAXN 3000005#define MOD1 12000017#define MOD2 15000127#define ll long long#define pii pair<ll,ll>using namespace std;map<pii,ll> p;ll read1(){ ll ret=0; char c=getchar(); do{ ret=ret*10+c-'0'; c=getchar(); }while('0'<=c&&c<='9'); return ret;}pii read2(){ ll ret1=0,ret2=0; char c=getchar(); do{ ret1=ret1*29+(c-64); ret2=ret2*37+(c-64); c=getchar(); }while('a'<=c&&c<='z'); return make_pair(ret1,ret2);} int main(){// freopen("liverpool8.in","r",stdin);// freopen("T1.out","w",stdout); int n=read1(); for(int i=1;i<=n;i++){ pii t1=read2(); int t2=read1(); p.insert(map<pii,ll>::value_type(t1,t2)); } int m=read1(); for(int i=1;i<=m;i++){ int x=read1(); ll ans=0; int ok=1; for(int j=1;j<=x;j++){ pii t=read2(); if(p.count(t)){ ans+=p[t]; } else{ ok=0; } } if(ok) printf("%lld\n",ans); else printf("-1\n"); } return 0;}
正解是字典树:#include<cstdio>#include<cstdlib>#include<algorithm>#include<cstring>using namespace std;struct Trie{Trie *Next[26];int Val;Trie(){memset(Next,0,sizeof(Next));Val=-1;}};int read(){int ret=0;char c=getchar();do{ret=ret*10+c-'0';c=getchar();}while('0'<=c&&c<='9');return ret;}Trie *root;int main(){//freopen("T2.in","r",stdin);root=new Trie;int n=read();for(int i=1;i<=n;i++){Trie *p=root,*q;while(1){char c=getchar();if('a'<=c&&c<='z'){c-=97;if(p->Next[c]){p=p->Next[c];}else{q=new Trie;p->Next[c]=q;p=p->Next[c];}}else{q->Val=read();break;}}}int T=read();for(int i=1;i<=T;i++){int x=read();int ok=1;long long ans=0;for(int j=1;j<=x;j++){Trie *p=root;while(1){char c=getchar();if('a'<=c&&c<='z'){c-=97;if(p->Next[c]){p=p->Next[c];}else{ok=0;}}else{if(p->Val!=-1){ans+=p->Val;}else{ok=0;}break;}}}if(!ok){printf("-1\n");}else{printf("%lld\n",ans);}}return 0;}
T2:紫色百合
当时时间不够了,草草写了一个暴力:
#include<cstdio>#include<cstdlib>#include<algorithm>#include<cstring>#include<vector>#define MOD 998244353#define ll long longusing namespace std;int n;ll p;vector<ll> s;ll find(int k,ll sum){ ll ret=sum; for(int i=k;i<s.size();i++){ ret+=find(i+1,sum*s[i]); } return ret;}int check(){ ll cnt=1; for(int i=0;i<s.size();i++){ cnt+=find(i+1,s[i]); } if(cnt==p){ return 1; } return 0;}int main(){// freopen("T2.in","r",stdin); int ans=0; scanf("%d%lld",&n,&p); p=(1<<p); for(int i=0;i<(1<<n);i++){ int t=0; s.clear(); for(int k=i,p=1;k;k>>=1,p++){ if(k&1){ s.push_back((1<<p)-1); } } if(check()){ ans++; if(MOD==ans){ ans=0; } } } printf("%d\n",ans); return 0;}后来发现经过数学变换可以转化为:
在1~n中选若干个数,使得它们的和为P,共有多少方案
用简单递推,超时:
#include<cstdio>#include<cstdlib>#include<algorithm>#include<cstring>#define MAXN 100005#define MOD 998244353using namespace std;int f[MAXN];int n,p;int main(){scanf("%d%d",&n,&p);f[0]=1;for(int i=1;i<=n;i++){for(int j=p;j>=i;j--){f[j]=(f[j]+f[j-i])%MOD;}}printf("%d\n",f[p]);return 0;}正解是考虑最多只能选O(sqrt(P))个物体,原因是(1+n)*n/2应该小于等于P
充分利用这样的性质做个递推式:f[i][j]=f[i-1][j-i]+f[i][j-i]-f[i-1][j-(N+1)] AC
#include<cstdio>#include<cstdlib>#include<algorithm>#include<cstring>#include<cmath>#define MOD 998244353#define MAXN 100005using namespace std;int n,p;int f[450][MAXN];int main(){//freopen("data.in","r",stdin);scanf("%d%d",&n,&p);for(int i=1;i<=n;i++){f[1][i]=1;}int Q=min(n,(int)(sqrt((double)(p<<1))));for(int i=2;i<=Q;i++){for(int j=i;j<=p;j++){f[i][j]=(f[i-1][j-i]+f[i][j-i])%MOD;if(j>n){f[i][j]=(f[i][j]-f[i-1][j-(n+1)]+MOD)%MOD;}}}int ans=0;for(int i=1;i<=Q;i++){ans=(ans+f[i][p])%MOD;}printf("%d\n",ans);return 0;}这种数学题目感觉挺难的,各种细节都要考虑到
T3:银河战舰
一开始做了线段树,不考虑旋转的情况了,
但仍然很难写,要定义三个懒标记优先级
#include<cstdio>#include<cstdlib>#include<algorithm>#include<cstring>#define MAXN 100005#define pii pair<double,double>using namespace std;pii dat[MAXN*4];pii add[MAXN*4];int dui[2][MAXN*4];bool change[MAXN*4];int n;pii a[MAXN];bool NZ(pii t){return (t.first!=0||t.second!=0);}void build(int k,int L,int R){if(L>=R){return;}dui[1][k]=dui[0][k]=1;if(L+1==R){dat[k]=a[L];return;}int mid=((L+R)>>1);build(k<<1,L,mid);build((k<<1)|1,mid,R);}void pushdown(int k){int lc=(k<<1),rc=((k<<1)|1);if(NZ(add[k])){dat[k].first+=add[k].first;dat[k].second+=add[k].second;if(!change[lc]){add[lc].first+=dui[1][lc]*add[k].first;add[lc].second+=dui[0][lc]*add[k].second;}else{add[lc].first+=dui[1][lc]*add[k].second;add[lc].second+=dui[0][lc]*add[k].first;}if(!change[rc]){add[rc].first+=dui[1][rc]*add[k].first;add[rc].second+=dui[0][rc]*add[k].second;}else{add[rc].first+=dui[1][rc]*add[k].second;add[rc].second+=dui[0][rc]*add[k].first;}add[k].first=add[k].second=0;}if(-1==dui[1][k]){dat[k].first*=dui[1][k];if(!change[lc]){dui[1][lc]*=dui[1][k];}else{dui[0][lc]*=dui[1][k];}if(!change[rc]){dui[1][rc]*=dui[1][k];}else{dui[0][rc]*=dui[1][k];}dui[1][k]=1;}if(-1==dui[0][k]){dat[k].second*=dui[0][k];if(!change[lc]){dui[0][lc]*=dui[0][k];}else{dui[1][lc]*=dui[0][k];}if(!change[rc]){dui[0][rc]*=dui[0][k];}else{dui[1][rc]*=dui[0][k];}dui[0][k]=1;}if(change[k]){swap(dat[k].first,dat[k].second);change[lc]=(!change[lc]);change[rc]=(!change[rc]);change[k]=0;}}void Add(int a,int b,int k,int L,int R,pii t){if(b<=L||R<=a){return;}else if(a<=L&&R<=b){if(NZ(add[k])||dui[1][k]||dui[0][k]||change[k]){pushdown(k);}add[k].first+=t.first;add[k].second+=t.second;}else{if(NZ(add[k])||dui[1][k]||dui[0][k]||change[k]){pushdown(k);}Add(a,b,k<<1,L,(L+R)>>1,t);Add(a,b,(k<<1)|1,(L+R)>>1,R,t);}}void Dui(int a,int b,int k,int L,int R,int t){if(b<=L||R<=a){return;}else if(a<=L&&R<=b){if(NZ(add[k])||dui[1][k]||dui[0][k]||change[k]){pushdown(k);}dui[t][k]*=-1;}else{if(NZ(add[k])||dui[1][k]||dui[0][k]||change[k]){pushdown(k);}Dui(a,b,k<<1,L,(L+R)>>1,t);Dui(a,b,(k<<1)|1,(L+R)>>1,R,t);}}void Change(int a,int b,int k,int L,int R){if(b<=L||R<=a){return;}else if(a<=L&&R<=b){change[k]=!(change[k]);}else{if(NZ(add[k])||dui[1][k]||dui[0][k]||change[k]){pushdown(k);}Change(a,b,k<<1,L,(L+R)>>1);Change(a,b,(k<<1)|1,(L+R)>>1,R);}}void Push(int k,int L,int R){if(L>=R){return;}if(NZ(add[k])||dui[1][k]||dui[0][k]||change[k]){pushdown(k);}if(L+1==R){a[L]=dat[k];return;}int mid=((L+R)>>1);Push(k<<1,L,mid);Push((k<<1)|1,mid,R);}int main(){//freopen("T3.in","r",stdin);//freopen("my.out","w",stdout);scanf("%d",&n);for(int i=1;i<=n;i++){scanf("%lf%lf",&a[i].first,&a[i].second);}build(1,1,n+1);int m;scanf("%d",&m);for(int i=1;i<=m;i++){char c;int L,R;scanf(" %c",&c);scanf("%d%d",&L,&R);if('M'==c){pii t;scanf("%lf%lf",&t.first,&t.second);Add(L,R+1,1,1,n+1,t);}else if('X'==c||'Y'==c){int t=((c=='Y')?1:0);Dui(L,R+1,1,1,n+1,t);}else if('O'==c){Change(L,R+1,1,1,n+1);}//debug(i);}Push(1,1,n+1);for(int i=1;i<=n;i++){if(0==a[i].first){printf("0.00 ");}else{printf("%.2f ",a[i].first);}if(0==a[i].second){printf("0.00\n");}else{printf("%.2f\n",a[i].second);}}return 0;}后来发现所有操作都可视为矩阵线性变换,
即(x y 1)乘不同的矩阵即可进行不同的操作,
然后矩阵线段树,这样只会有一种乘的操作了
#include<cstdio>#include<cstdlib>#include<algorithm>#include<cstring>#include<cmath>#define MAXN 100005using namespace std;struct Mat{int x,y;double s[3][3];Mat(){x=y=3;memset(s,0,sizeof(s));s[0][0]=s[1][1]=s[2][2]=1;}Mat operator * (const Mat &A){Mat ret;ret.x=x; ret.y=A.y;memset(ret.s,0,sizeof(ret.s));for(int i=0;i<x;i++){for(int j=0;j<A.y;j++){for(int k=0;k<y;k++){ret.s[i][j]+=s[i][k]*A.s[k][j];}}}return ret;}};int n;double pi=acos(-1);Mat dat[MAXN*4];Mat a[MAXN];void pushdown(int k){dat[k<<1]=dat[k<<1]*dat[k];dat[(k<<1)|1]=dat[(k<<1)|1]*dat[k];for(int i=0;i<3;i++){for(int j=0;j<3;j++){if(i==j){dat[k].s[i][j]=1;}else{dat[k].s[i][j]=0;}}}}void Add(int a,int b,int k,int L,int R,Mat t){if(b<=L||R<=a){return;}else if(a<=L&&R<=b){dat[k]=dat[k]*t;}else{pushdown(k);Add(a,b,k<<1,L,(L+R)>>1,t);Add(a,b,(k<<1)|1,(L+R)>>1,R,t);}}void Push(int k,int L,int R){if(L+1==R){a[L]=a[L]*dat[k];for(int i=0;i<3;i++){for(int j=0;j<3;j++){if(i==j){dat[k].s[i][j]=1;}else{dat[k].s[i][j]=0;}}}return;}pushdown(k);Push(k<<1,L,(L+R)>>1);Push((k<<1)|1,(L+R)>>1,R);}void debug(){Push(1,1,n+1);for(int i=1;i<=n;i++){printf("%.2f %.2f\n",a[i].s[0][0],a[i].s[0][1]);}printf("\n");}int main(){//freopen("T3.in","r",stdin);//freopen("my.out","w",stdout);scanf("%d",&n);for(int i=1;i<=n;i++){double x,y;scanf("%lf%lf",&x,&y);a[i].x=1; a[i].y=3;memset(a[i].s,0,sizeof(a[i].s));a[i].s[0][0]=x,a[i].s[0][1]=y,a[i].s[0][2]=1;}//debug();int T;scanf("%d",&T);for(int i=1;i<=T;i++){char c;int L,R;scanf(" %c",&c);scanf("%d%d",&L,&R);if('M'==c){double x,y;scanf("%lf%lf",&x,&y);Mat t;t.s[2][0]=x; t.s[2][1]=y;Add(L,R+1,1,1,n+1,t);}else if('X'==c){Mat t;t.s[1][1]=-1;Add(L,R+1,1,1,n+1,t);}else if('Y'==c){Mat t;t.s[0][0]=-1;Add(L,R+1,1,1,n+1,t);}else if('O'==c){Mat t;t.s[0][0]=t.s[1][1]=0;t.s[0][1]=t.s[1][0]=1;Add(L,R+1,1,1,n+1,t);}else{double aa;scanf("%lf",&aa);aa=aa*pi/180;Mat t;t.s[0][0]=cos(aa); t.s[0][1]=sin(aa);t.s[1][0]=-sin(aa); t.s[1][1]=cos(aa);Add(L,R+1,1,1,n+1,t);}//debug();}Push(1,1,n+1);for(int i=1;i<=n;i++){printf("%.2f %.2f\n",a[i].s[0][0],a[i].s[0][1]);}return 0;}总结:
这次模拟题说实话真的挺难的,我没得几分,细节方面经常炸
多注意细节还是很有必要啊ToT
阅读全文
0 0
- 计蒜客 2017 NOIP 提高组模拟赛(二)Day2
- 计蒜客 2017 NOIP 提高组模拟赛(一)Day2
- 2017 NOIP 提高组模拟赛(四)Day2(计蒜客)
- 计蒜客 2017 NOIP 提高组模拟赛(三)Day2 小区划分
- [DP] 计蒜客 2017 NOIP模拟赛(二)Day2 T2.紫色百合
- 计蒜客 2017 NOIP 提高组模拟赛(二)Day1 A. 邻家男孩
- 计蒜客 2017 NOIP 提高组模拟赛(一)题解
- 计蒜客 2017 NOIP 提高组模拟赛(一)Day1
- 计蒜客NOIP提高组模拟Day2,Pro1蒜头君的兔子
- 2- noip模拟赛 DAY2
- 【初中部 NOIP提高组 二试】模拟赛B总结
- NOIP 2017 提高组 Day2 T1 奶酪 cheese.cpp
- Noip 2017 提高组 Day2 T1 奶酪(并查集)
- NOIP 2015 提高组 day2 解题报告
- NOIp提高组2016 Day2 T2 蚯蚓
- contesthunter NOIP模拟赛Day2 8.10
- 洛谷 NOIP 模拟 DAY2
- 【初中部 NOIP提高组 】模拟赛A
- 网页抓取方式(五)--selenium
- NoSQL简介
- margin-top margin-left border
- msvcr120.dll WIN7 64位/32位丢失怎么办
- robot framework 源码分析学习
- 计蒜客 2017 NOIP 提高组模拟赛(二)Day2
- Python机器学习Sklearn入门案例(上)
- Android5.0,6.0,7.0,8.0新特性整理
- 冒泡排序逻辑
- 设计模式(四)——JDK中的那些工厂方法
- [数学模型]商人怎样安全过河
- 在网上书城项目中对数据库连接错误的解决
- Java并发编程(一)--AbstractQueuedSynchronizer
- MySQL登录时出现的Access denied for user 'root'@'xxx.xxx.xxx.xxx' (using password: YES) 的解决办法