$NOIP2012$ 题解报告
目录
$Luogu\ P1079$ $Vigenère$密码$(\ √\ )$
$Luogu\ P1080$ 国王游戏$(\ √\ )$
$Luogu\ P1081$ 开车旅行( )
$Luogu\ P1082$ 同余方程$(\ √\ )$
$Luogu\ P1083$ 借教室$(\ √\ )$
$Luogu\ P1084$ 疫情控制$(\ √\ )$
$Luogu\ P1079$ $Vigenère$密码
很水的模拟题,注意看清题目!
1 #include<bits/stdc++.h> 2 #define ri register int 3 #define ll long long 4 #define rl register ll 5 #define go(i,a,b) for(ri i=a;i<=b;i++) 6 #define back(i,a,b) for(ri i=a;i>=b;i--) 7 #define g() getchar() 8 #define il inline 9 #define pf printf 10 #define mem(a,b) memset(a,b,sizeof(a)) 11 using namespace std; 12 il int fr(){ 13 ri w=0,q=1;char ch=g(); 14 while(ch<'0'||ch>'9'){if(ch=='-')q=-1;ch=g();} 15 while(ch>='0'&&ch<='9')w=(w<<1)+(w<<3)+ch-'0',ch=g(); 16 return w*q; 17 } 18 char k[102],s1[1002],s2[1002]; 19 int n,m,add='a'-'A'; 20 il char cal(char x,char y){ 21 bool type=0;char ans; 22 //cout<<"x="<<x<<" y="<<y<<endl; 23 int X,Y; 24 if(y>='a'&&y<='z')type=1,Y=y-add-'A'; 25 else Y=y-'A'; 26 if(x>='a'&&x<='z')X=x-add-'A'; 27 else X=x-'A'; 28 //cout<<"X="<<X<<" Y="<<Y<<endl; 29 if(type)ans=(char)(Y-X+26)%26+add+'A'; 30 else ans=(char)(Y-X+26)%26+'A'; 31 //while(ans<0)ans+=26; 32 //cout<<"ans="<<ans<<endl; 33 return ans; 34 } 35 int main(){ 36 freopen("1.in","r",stdin); 37 freopen("1.out","w",stdout); 38 scanf("%s",k);n=strlen(k); 39 scanf("%s",s1);m=strlen(s1); 40 //cout<<"A="<<(int)'A'<<" a="<<(int)'a'<<" add="<<add<<endl; 41 //char c=(char)87;cout<<"c="<<c<<endl; 42 go(i,0,m-1)s2[i]=cal(k[i%n],s1[i]); 43 go(i,0,m-1)pf("%c",s2[i]);puts(""); 44 return 0; 45 }
$Luogu\ P1080$ 国王游戏
贪心经典例题,注意是根据什么排序的
1 #include<bits/stdc++.h> 2 using namespace std; 3 inline int read() 4 { 5 int ret=0,f=1; 6 char ch=getchar(); 7 while(ch>'9'||ch<'0') 8 { 9 if(ch=='-') 10 f=-1; 11 ch=getchar(); 12 } 13 while(ch>='0'&&ch<='9') 14 { 15 ret=(ret<<1)+(ret<<3)+ch-'0'; 16 ch=getchar(); 17 } 18 return ret*f; 19 } 20 int n,lens=1,lenm=1,lena=1,sum[10005]={0,1},maxn[10005]={0,1},ans[10005]; 21 struct node 22 { 23 int a; 24 int b; 25 }s[1005]; 26 inline bool cmp(node x,node y) 27 { 28 return x.a*x.b<y.a*y.b; 29 } 30 inline void mul(int x) 31 { 32 int tmp=0; 33 for(register int i=1;i<=lens;i++) 34 sum[i]*=x; 35 for(register int i=1;i<=lens;i++) 36 { 37 tmp+=sum[i]; 38 sum[i]=tmp%10; 39 tmp/=10; 40 } 41 while(tmp) 42 { 43 lens++; 44 sum[lens]=tmp%10; 45 tmp/=10; 46 } 47 } 48 inline void div(int x) 49 { 50 memset(ans,0,sizeof(ans)); 51 lena=lens; 52 int tmp=0; 53 for(register int i=lena;i;i--) 54 { 55 tmp*=10; 56 tmp+=sum[i]; 57 if(tmp>=x) 58 { 59 ans[i]=tmp/x; 60 tmp%=x; 61 } 62 } 63 while(ans[lena]==0) 64 { 65 if(lena==1) 66 break; 67 lena--; 68 } 69 } 70 inline void cmp1() 71 { 72 if(lena>lenm) 73 { 74 for(register int i=1;i<=lena;i++) 75 maxn[i]=ans[i]; 76 lenm=lena; 77 } 78 else if(lenm==lena) 79 { 80 for(register int i=lena;i;i--) 81 { 82 if(maxn[i]<ans[i]) 83 { 84 for(register int j=1;j<=lena;j++) 85 maxn[j]=ans[j]; 86 lenm=lena; 87 break; 88 } 89 } 90 } 91 } 92 inline void write() 93 { 94 for(register int i=lenm;i;i--) 95 printf("%d",maxn[i]); 96 } 97 int main() 98 { 99 n=read(); 100 s[0].a=read(); 101 s[0].b=read(); 102 for(register int i=1;i<=n;i++) 103 { 104 s[i].a=read(); 105 s[i].b=read(); 106 } 107 sort(s+1,s+n+1,cmp); 108 for(register int i=1;i<=n;i++) 109 { 110 mul(s[i-1].a); 111 div(s[i].b); 112 cmp1(); 113 } 114 write(); 115 return 0; 116 }
$Luogu\ P1081$ 开车旅行
之前写过一篇题解,贴个$link\to$戳这里
代码还没过$QAQ$
$Luogu\ P1082$ 同余方程
扩展欧几里得模板
1 #include<bits/stdc++.h> 2 #define ll long long 3 using namespace std; 4 ll a,b,x,y; 5 ll exgcd(ll a,ll b,ll &x,ll &y){ 6 if(!b) {x=1;y=0;return a;} 7 ll d=exgcd(b,a%b,x,y); 8 ll z=x;x=y;y=z-y*(a/b); 9 return d; 10 } 11 int main(){ 12 cin>>a>>b; 13 ll ans=exgcd(a,b,x,y); 14 cout<<(x%b+b)%b<<endl; 15 return 0; 16 }
$Luogu\ P1083$ 借教室
线段树大法好
直接线段树……挺板子的?
1 #include<bits/stdc++.h> 2 #define ri register int 3 #define ll long long 4 #define rl register ll 5 #define go(i,a,b) for(ri i=a;i<=b;i++) 6 #define back(i,a,b) for(ri i=a;i>=b;i--) 7 #define g() getchar() 8 #define il inline 9 #define pf printf 10 #define mem(a,b) memset(a,b,sizeof(a)) 11 using namespace std; 12 il int fr(){ 13 ri w=0,q=1;char ch=g(); 14 while(ch<'0'||ch>'9'){if(ch=='-')q=-1;ch=g();} 15 while(ch>='0'&&ch<='9')w=(w<<1)+(w<<3)+ch-'0',ch=g(); 16 return w*q; 17 } 18 const int N=1e6+2; 19 int n,m,a[N]; 20 struct Tree{ 21 int l,r,tag,mn; 22 }t[N<<2]; 23 il void build(ri p,ri l,ri r){ 24 if(l>r)return; 25 if(l==r){t[p]=(Tree){l,r,0,a[l]};return;} 26 ri mid=(l+r)>>1; 27 build(p<<1,l,mid);build((p<<1)+1,mid+1,r); 28 t[p]=(Tree){l,r,0,min(t[p<<1].mn,t[(p<<1)+1].mn)}; 29 return; 30 } 31 il void push(ri p){ 32 if(t[p].tag==0)return; 33 t[p<<1].mn-=t[p].tag;t[p<<1|1].mn-=t[p].tag; 34 t[p<<1].tag+=t[p].tag;t[(p<<1)+1].tag+=t[p].tag; 35 t[p].tag=0;return; 36 } 37 il bool change(ri p,ri l,ri r,ri d){ 38 if(l<=t[p].l&&r>=t[p].r){ 39 if(t[p].mn<d)return 0; 40 t[p].tag+=d;t[p].mn-=d;return 1; 41 } 42 ri mid=(t[p].l+t[p].r)>>1;push(p); 43 bool ans=1; 44 if(l<=mid)ans&=change(p<<1,l,r,d); 45 if(r>mid)ans&=change((p<<1)+1,l,r,d); 46 t[p].mn=min(t[p<<1|1].mn,t[p<<1].mn); 47 return ans; 48 } 49 int main(){ 50 n=fr();m=fr(); 51 go(i,1,n)a[i]=fr(); 52 build(1,1,n); 53 go(i,1,m){ 54 ri d=fr(),l=fr(),r=fr(); 55 if(!change(1,l,r,d)){puts("-1");pf("%d\n",i);return 0;} 56 } 57 puts("0");return 0; 58 }
我考虑什么时候再写个二分的做法叭
$Luogu\ P1084$ 疫情控制
为什么大家都觉得这题挺难写昂?我感觉我没调好久$QAQ$
首先最优的显然是每个军队都走到能走到的深度最小的节点,然后如果有军队可以走到根节点,就先停在根节点的子节点。然后我们再扫描根节点的所有子节点中有哪些是到叶子节点的路径还没有驻扎军队的,用那些可以到根节点的军队与这些根节点的子节点去匹配即可
代码确实有点难写
1 #include<bits/stdc++.h> 2 #define ri register int 3 #define ll long long 4 #define rl register ll 5 #define go(i,a,b) for(ri i=a;i<=b;i++) 6 #define back(i,a,b) for(ri i=a;i>=b;i--) 7 #define g() getchar() 8 #define il inline 9 #define pf printf 10 #define mem(a,b) memset(a,b,sizeof(a)) 11 #define E(i,x) for(ri i=hd[x];i;i=e[i].nxt) 12 #define t(i) e[i].to 13 #define P pair<ll,int> 14 #define mp make_pair 15 using namespace std; 16 il int fr(){ 17 ri w=0,q=1;char ch=g(); 18 while(ch<'0'||ch>'9'){if(ch=='-')q=-1;ch=g();} 19 while(ch>='0'&&ch<='9')w=(w<<1)+(w<<3)+ch-'0',ch=g(); 20 return w*q; 21 } 22 const int N=50002; 23 int n,m,ed,hd[N],f[N][20],dep[N],army[N],son; 24 ll dis[N],r,l,ans; 25 bool v[N],as; 26 priority_queue<ll>q1,q2; 27 struct edge{ 28 int nxt,to,w; 29 }e[N<<1]; 30 il void build(int u,int v,int w){e[++ed]=(edge){hd[u],v,w};hd[u]=ed;return;} 31 il void Tree(int x,int fa){ 32 dep[x]=dep[fa]+1;f[x][0]=fa; 33 go(i,1,19)f[x][i]=f[f[x][i-1]][i-1]; 34 E(i,x){ 35 if(t(i)==fa)continue; 36 if(x==1)son++; 37 dis[t(i)]=dis[x]+e[i].w;Tree(t(i),x); 38 } 39 return; 40 } 41 il bool dfs(int x,int fa){ 42 if(v[x])return 1; 43 bool fin=0; 44 E(i,x){ 45 if(t(i)==fa)continue; 46 fin=1; 47 if(!dfs(t(i),x))return 0; 48 } 49 if(fin)return 1; 50 return 0; 51 } 52 il bool check(ll x){ 53 //cout<<"mid="<<x<<endl; 54 while(!q1.empty())q1.pop(); 55 while(!q2.empty())q2.pop();mem(v,0); 56 P a[N];int tot=0;bool b[N];mem(b,0); 57 go(i,1,m){ 58 int A=army[i];ll nw=x; 59 //cout<<"x="<<A<<endl; 60 back(j,19,0)if(dep[f[A][j]]>dep[1]&&(dis[A]-dis[f[A][j]])<=nw) 61 nw-=(dis[A]-dis[f[A][j]]),A=f[A][j]; 62 //cout<<"x'="<<A<<endl; 63 if(nw>dis[A]&&f[A][0]==1)a[++tot]=mp(nw-dis[A],A); 64 else v[A]=1; 65 } 66 E(i,1)if(!dfs(t(i),1))b[t(i)]=1; 67 sort(a+1,a+1+tot); 68 go(i,1,tot) 69 if(b[a[i].second]&&a[i].first<dis[a[i].second])b[a[i].second]=0; 70 else q1.push(-a[i].first); 71 E(i,1)if(b[t(i)])q2.push(-dis[t(i)]); 72 if((int)q1.size()<(int)q2.size())return 0; 73 while((!q2.empty())&&(!q1.empty())){ 74 ll d1=-q1.top();q1.pop(); 75 ll d2=-q2.top();if(d1>=d2)q2.pop(); 76 } 77 if(q1.empty()&&(!q2.empty()))return 0; 78 else return 1; 79 } 80 int main(){ 81 //freopen("1.in","r",stdin); 82 //freopen("1.out","w",stdout); 83 n=fr(); 84 go(i,1,n-1){ 85 int u=fr(),v=fr(),w=fr();r+=w; 86 build(u,v,w);build(v,u,w); 87 } 88 Tree(1,0);m=fr(); 89 go(i,1,m){ 90 int x=fr(); 91 v[x]=1;army[i]=x; 92 } 93 if(son>m){puts("-1");return 0;} 94 while(l<=r){ 95 ll mid=(l+r)>>1; 96 //cout<<"l="<<l<<" r="<<r<<" mid="<<mid<<endl; 97 if(check(mid))r=mid-1,ans=mid,as=1; 98 else l=mid+1; 99 } 100 if(as)pf("%lld\n",ans); 101 else puts("-1"); 102 return 0; 103 }