2019佳木斯集训 Day8
T1
数学数列题,建议无论学不学信奥的同学都做一做
(我用了1个半小时,证明了10分钟推出来的式子)
思路:可以推出式子也可以二分暴力求,easy
1 #include <bits/stdc++.h> 2 using namespace std; 3 double a1,an1,ans; 4 int n; 5 double bigg; 6 double a[3010]; 7 double d[3010]; 8 int main(){ 9 scanf("%d",&n); 10 scanf("%lf%lf",&a1,&an1); 11 for(register int i=1;i<=n;i++){ 12 scanf("%lf",&d[i]); 13 d[i]*=2; 14 d[i]+=d[i-1]; 15 } 16 for(register int i=2;i<=n;i++) bigg+=d[i]; 17 //printf("%d %d %d") 18 ans=(a1*n+an1-bigg-d[1])/(n+1); 19 printf("%.2lf",ans); 20 return 0; 21 }
T2
超简单的大贪心,贪就完了
思路:首先输入,跑两个n^2,第一个跑田忌赢齐王的情况
其中有个特判,就是如果当前马能赢且比上一个搜到能战胜他的马
还小那咱们就用小的,然后把跑完的两匹马标记一下,避免搜重
然后第二个n^2跑平局的情况
1 #include <bits/stdc++.h> 2 using namespace std; 3 int a[1010]; 4 int b[1010]; 5 bool visa[1010],visb[1010]; 6 int T,n,w,num1,num2; 7 bool cmp(int x,int y){ return x>y; } 8 int main(){ 9 scanf("%d",&T); 10 while(T--){ 11 memset(visa,0,sizeof(visa)); 12 memset(visb,0,sizeof(visb)); 13 num1=0,num2=0; 14 scanf("%d",&n); 15 for(register int i=1;i<=n;i++) scanf("%d",&a[i]); 16 for(register int i=1;i<=n;i++) scanf("%d",&b[i]); 17 sort(b+1,b+n+1,cmp); 18 for(register int i=1;i<=n;i++){ 19 w=0; 20 if(visb[i]) continue; 21 for(register int j=1;j<=n;j++){ 22 if(visa[j]) continue; 23 if(a[j]<=b[i]) continue; 24 if(!w) w=j; 25 else if(w&&a[j]<a[w]) w=j; 26 } 27 if(w) visb[i]=1,visa[w]=1,num1++; 28 } 29 for(register int i=1;i<=n;i++){ 30 if(visb[i]) continue; 31 w=0; 32 for(register int j=1;j<=n;j++){ 33 if(visa[j]) continue; 34 if(a[j]==b[i]){w=j;break;} 35 } 36 if(w) visb[i]=1,visa[w]=1,num2++; 37 } 38 printf("%d\n",num1*200-(n-num1-num2)*200); 39 } 40 return 0; 41 }
T3
树dp,晓姐姐讲课,小姐姐nb
思路,树dp模板,转移方程为,dp[x][work(edge[i].w+j)]+=dp[v][j];
但是要注意每次更新之前要先累加ans要不会漏判,最后两数要约分,不然就挂了....
1 #include <bits/stdc++.h> 2 using namespace std; 3 struct node{ 4 int nxt,to,w; 5 }edge[100010]; 6 int head[100010]; 7 int cnt,k,n,u,v,w,ans; 8 int dp[50010][3]; 9 void addedge(int from,int to,int w){ 10 cnt++; 11 edge[cnt].w=w; 12 edge[cnt].to=to; 13 edge[cnt].nxt=head[from]; 14 head[from]=cnt; 15 } 16 int work(int a){ 17 return (a%3+3)%3; 18 } 19 void dfs(int x,int fa){ 20 dp[x][0]=1; 21 for(register int i=head[x];i;i=edge[i].nxt){ 22 int v=edge[i].to; 23 if(v==fa) continue; 24 dfs(v,x); 25 for(register int j=0;j<=2;j++){ 26 ans+=dp[v][j]*dp[x][(work(-edge[i].w-j))]*2; 27 } 28 for(register int j=0;j<=2;j++){ 29 dp[x][work(edge[i].w+j)]+=dp[v][j]; 30 } 31 } 32 } 33 int main(){ 34 scanf("%d",&n); 35 for(register int i=1;i<n;i++){ 36 scanf("%d%d%d",&u,&v,&w); 37 addedge(u,v,w); 38 addedge(v,u,w); 39 } 40 dfs(1,0); 41 ans+=n; 42 int qwq=__gcd(n*n,ans); 43 printf("%d/%d",ans/qwq,n*n/qwq); 44 return 0; 45 }
end;