Day2下午解題報告
阿新 • • 發佈:2017-10-29
algo eve 數據 oid 素數表 eof ide bool struct
預計分數:100+100+30=230
實際分數:100+100+30=230
人品爆發&&智商爆發&&手感爆發
T3數據好水,,要是把數組開大一點的話還能多得10分,,,
T1洗澡
原題,不多說了。。
當時在北京花了接近一個小時才A..
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cmath> 5 using namespace std; 6 const int MAXN=1e6; 7 constView Codeint INF=0x7ffff; 8 inline int read() 9 { 10 char c=getchar();int flag=1,x=0; 11 while(c<‘0‘||c>‘9‘) {if(c==‘-‘) flag=-1;c=getchar();} 12 while(c>=‘0‘&&c<=‘9‘) x=x*10+c-48,c=getchar();return x*flag; 13 } 14 char a[MAXN]; 15 int main() 16 { 17 //freopen("shower.in","r",stdin);18 //freopen("shower.out","w",stdout); 19 scanf("%s",a+1); 20 int l=strlen(a+1); 21 int now=0,ans=0; 22 for(int i=1;i<=l;i++) 23 { 24 if(a[i]==‘(‘) 25 { 26 if(now==l/2) ans++,now--;//修改 27 else now++; 28 } 29 else30 { 31 if(now==0) ans++,now++; 32 else if(now<=l/2) now--; 33 } 34 } 35 printf("%d",ans+now/2); 36 return 0; 37 }
T2日記
一開始想到了70分的做法,寫著寫著就會100分的做法了。。
先打個素數表,
對於每次詢問的n
upperbound一個值,再在k-這個值之間二分,
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cmath> 5 #include<algorithm> 6 #define LL long long 7 using namespace std; 8 const LL MAXN=1e6+10; 9 const LL INF=0x7ffff; 10 inline LL read() 11 { 12 char c=getchar();LL flag=1,x=0; 13 while(c<‘0‘||c>‘9‘) {if(c==‘-‘) flag=-1;c=getchar();} 14 while(c>=‘0‘&&c<=‘9‘) x=x*10+c-48,c=getchar();return x*flag; 15 } 16 LL T; 17 LL vis[MAXN]; 18 LL prime[MAXN]; 19 LL sprime[MAXN]; 20 LL tot=0; 21 LL check(LL mid,LL n,LL k) 22 { 23 if(sprime[mid]-sprime[mid-k]<=n) return 1; 24 else return 0; 25 } 26 int main() 27 { 28 // freopen("diary.in","r",stdin); 29 // freopen("diary.out","w",stdout); 30 for(LL i=2;i<=sqrt(1e6);i++) 31 { 32 if(vis[i]==0) 33 for(LL j=i*i;j<=1e6;j+=i) 34 vis[j]=1; 35 } 36 for(LL i=2;i<=1e6;i++) if(vis[i]==0) 37 prime[++tot]=i; 38 //for(LL i=1;i<=tot;i++) 39 // printf("%d\n",prime[i]); 40 T=read(); 41 for(LL i=1;i<=tot;i++) 42 sprime[i]=sprime[i-1]+prime[i]; 43 while(T--) 44 { 45 LL n=read(),k=read(); 46 LL pos=upper_bound(prime+1,prime+tot+1,n)-prime;pos--; 47 LL ans=0; 48 bool flag=0; 49 LL l=k,r=pos; 50 while(l<=r) 51 { 52 LL mid=l+r>>1; 53 if(check(mid,n,k)) flag=1,ans=mid,l=mid+1; 54 else r=mid-1; 55 } 56 LL out=sprime[ans]-sprime[ans-k]; 57 if(flag==1) printf("%lld\n",out); 58 else printf("-1\n"); 59 } 60 return 0; 61 }View Code
T3洗衣
直覺告訴我,這題一定非常難,,
因為我連暴力都不會打,
想了幾分鐘,感覺30分可以做,就是比較奇葩,,,需要存2^m棵樹,
代碼很惡心,,不過還好沒敲炸
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cmath> 5 #include<queue> 6 7 using namespace std; 8 const int MAXN=1001; 9 const int INF=0x7ffff; 10 const int mod=1e9+7; 11 inline int read() 12 { 13 char c=getchar();int flag=1,x=0; 14 while(c<‘0‘||c>‘9‘) {if(c==‘-‘) flag=-1;c=getchar();} 15 while(c>=‘0‘&&c<=‘9‘) x=x*10+c-48,c=getchar();return x*flag; 16 } 17 struct TREE 18 { 19 struct node 20 { 21 int u,v,w,nxt; 22 }edge[MAXN]; 23 int head[MAXN]; 24 int num; 25 int siz;//樹的大小 26 int bg;//第一個節點的編號 27 TREE() 28 { 29 memset(head,-1,sizeof(head)); 30 num=1;siz=1;bg=1; 31 } 32 void add_edge(int x,int y,int z) 33 { 34 edge[num].u=x; 35 edge[num].v=y; 36 edge[num].w=z; 37 edge[num].nxt=head[x]; 38 head[x]=num++; 39 } 40 }tree[MAXN]; 41 int treenum=0; 42 inline void merge(int t1,int n1,int t2,int n2,int val) 43 { 44 treenum++; 45 for(int i=1;i<=tree[t1].num-1;i++) 46 tree[treenum].add_edge(tree[t1].edge[i].u,tree[t1].edge[i].v,tree[t1].edge[i].w); 47 for(int i=1;i<=tree[t2].num-1;i++) 48 tree[treenum].add_edge(tree[t2].edge[i].u+tree[t1].siz,tree[t2].edge[i].v+tree[t1].siz,tree[t2].edge[i].w); 49 tree[treenum].add_edge(n1,n2+tree[t1].siz,val); 50 tree[treenum].add_edge(n2+tree[t1].siz,n1,val); 51 tree[treenum].siz=tree[t1].siz+tree[t2].siz; 52 } 53 int dis[MAXN]; 54 int vis[MAXN]; 55 int ans=0; 56 inline void BFS() 57 { 58 for(int k=0;k<=tree[treenum].siz-1;k++) 59 { 60 memset(dis,0,sizeof(dis)); 61 memset(vis,0,sizeof(vis)); 62 dis[k]=0; 63 queue<int>q; 64 q.push(k); 65 while(q.size()!=0) 66 { 67 int p=q.front(); 68 q.pop(); 69 for(int i=tree[treenum].head[p];i!=-1;i=tree[treenum].edge[i].nxt) 70 if(vis[tree[treenum].edge[i].v]==0) 71 vis[tree[treenum].edge[i].v]=1, 72 dis[tree[treenum].edge[i].v]=(dis[p]+tree[treenum].edge[i].w)%mod, 73 q.push(tree[treenum].edge[i].v); 74 } 75 for(int i=k+1;i<=tree[treenum].siz-1;i++) 76 ans=(ans+dis[i])%mod; 77 } 78 } 79 int main() 80 { 81 // freopen("cloth.in","r",stdin); 82 // freopen("cloth.out","w",stdout); 83 int n=read(); 84 for(int i=1;i<=n;i++) 85 { 86 int a=read(),b=read(),c=read(),d=read(),e=read(); 87 merge(a,c,b,d,e); 88 ans=0; 89 BFS(); 90 printf("%d\n",ans); 91 } 92 return 0; 93 }40分暴力
100分
考慮每一棵樹的組成
一棵樹的答案一定包含了左邊的樹的答案
$f[i]=f[j]+f[k]+dis[new]$
考慮如何計算$dis[new]$
dis[i]=原來的j+新加的(左邊樹的大小*右邊樹的大小)+原來的k
原來的j=siz[j]*所有點到p1點的距離
$k=siz[k]+g[k][p2]$//g在第k棵樹中所有點到達p的距離
考慮如何求g
dp
設i是由j,k合並而來
$g[i][p]=g[j][p]+L+dis[j][p][p1]*siz[k]+g[k][p2]$
——》會T會boom——》開map做記憶化搜索
dis[j][p][p3]+l+dis[k][p2][p4]記憶化搜索
總結:
這次考的好是有諸多方面的原因的。。
T1原題,T2不難,T3正解非常難,暴力需要較強的代碼能力
這一套題貌似就是為我量身定做的啊233333
Day2下午解題報告