Day2下午
虽然成绩不太好,但有点进入状态了。期望200 实际160,忘记加判断了。
T1
洗澡
【问题描述】
你是能看到第一题的friends 呢。
——hja
洗澡的地方,有一段括号序列,将一个括号修改一次需要1的代价(将左括
号变成右括号或者相反),求最小代价使得括号序列合法。
【输入格式】
一行一个括号序列。
【输出格式】
一行一个整数代表答案。
【样例输入】
())(
【样例输出】
2
【数据范围与规定】
对于50%的数据,括号序列长度不超过100。
对于100%的数据,括号序列长度不超过105且一定为偶数,只包含小括
号。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<iostream> #include<cstdio> #include<cstring> #include<queue> #include<vector> #include<cmath> #include<ctime> using namespace std; char s[100009]; int len; int ans,sum; int main() { freopen("shower.in","r",stdin); freopen("shower.out","w",stdout); cin>>(s+1); len=strlen(s+1); for(int i=1;i<=len;i++) { if(s[i]=='(') sum++; else sum--; if(sum<0) ans++,sum+=2; } if(sum) ans+=sum/2; cout<<ans; return 0; }
直接模拟。
T2
日记
【问题描述】
你是能看到第二题的 friends呢。
—— laekov
日记之中,写满了质数两个间如果没有其他那么则称为相 邻的质数。给定 𝑁,𝑘,询问不超过 𝑁的数中能够表示成连续 𝑘个质数之和的最大 的数是多少。
【输入格式】
第一行个整数 𝑇代表数据组。
对于每组数据,一行 行两个整数 𝑁,𝑘。
【输出格式】
对于每组数据,一行个整代表答案。如果不存在则输出 −1。
【样例输入】
3
20 2
20 3
20 4
【样例输出】
18
15
17
【数据范围与规定】
对于 20%的数据 ,1≤𝑁≤100。
对于 40%的数据 ,𝑇=1。
对于 另外 20%的数据 ,所有的 询问𝑁相等 。
对于 100%的数据 ,1≤𝑇<2000,1≤𝑁≤106。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<iostream> #include<cstdio> #include<cstring> #include<queue> #include<vector> #include<cmath> #include<ctime> using namespace std; const int N=1000000+4; int prime[N],cnt; bool is[N]; int T; void first() { cnt=0; for(int i=2;i<=N;i++) { if(!is[i]) prime[++cnt]=i; for(int j=1;j<=cnt;j++) { if(i*prime[j]>N) break; is[i*prime[j]]=1; if(i%prime[j]==0) break; } } return ; } int work(int mid,int len) { int sum=0; for(int i=mid;i<=mid+len-1;i++) sum+=prime[i]; return sum; } int main() { freopen("diary.in","r",stdin); freopen("diary.out","w",stdout); first(); scanf("%d",&T); for(int i=1,n,k;i<=T;i++) { scanf("%d%d",&n,&k); int j=1,sum=0,L,R,mid; if(n<=100) { j=1,sum=0; for(j=1;j<=k;j++) sum+=prime[j];j--; if(n<sum) { printf("-1\n"); continue; } while(sum+prime[j+1]-prime[j-k+1]<=n) sum=sum+prime[j+1]-prime[j-k+1],j++; printf("%d\n",sum); continue; } L=1,R=cnt-k+1; while(L<=R) { mid=(L+R)>>1; if(work(mid,k)<=n) L=mid+1; else R=mid-1; } for(j=min(cnt,L);j>=R;j--) if((sum=work(j,k))<=n) { printf("%d\n",sum); break; } } return 0; }
可恶啊,就差求个前缀和。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<iostream> #include<cstdio> #include<cstring> #include<queue> #include<vector> #include<cmath> #include<ctime> using namespace std; const int N=1000000+4; int prime[N],cnt; int f[N]; bool is[N]; int T; void first() { cnt=0; for(int i=2;i<=N;i++) { if(!is[i]) prime[++cnt]=i; for(int j=1;j<=cnt;j++) { if(i*prime[j]>N) break; is[i*prime[j]]=1; if(i%prime[j]==0) break; } } for(int i=1;i<=cnt;i++) f[i]=f[i-1]+prime[i]; return ; } int work(int mid,int len) { return f[mid+len-1]-f[mid-1];} int main() { freopen("diary.in","r",stdin); freopen("diary.out","w",stdout); first(); scanf("%d",&T); for(int i=1,n,k;i<=T;i++) { scanf("%d%d",&n,&k); int j=1,sum=0,L,R,mid; if(n<=100) { j=1,sum=0; j=k; sum=f[j]; if(n<sum) { printf("-1\n"); continue; } while(sum+prime[j+1]-prime[j-k+1]<=n) sum=sum+prime[j+1]-prime[j-k+1],j++; printf("%d\n",sum); continue; } sum=f[k]; if(n<sum) { printf("-1\n"); continue; } L=1,R=cnt-k+1; while(L<=R) { mid=(L+R)>>1; if(work(mid,k)<=n) L=mid+1; else R=mid-1; } for(j=min(cnt,L);j>=R;j--) if((sum=work(j,k))<=n) { printf("%d\n",sum); break; } } return 0; }
思路:先筛素数,可以先求个前缀和!然后二分起点。
T3
洗衣
【问题描述】
你是能看到第三题的 friends呢。
—— aoao
洗完衣服,就要晒在树上 洗完衣服,就要晒在树上 。但是这个世界并没有树,我们需要重新开始造。 但是这个世界并没有树,我们需要重新开始造。 我们一开始拥有 𝑇0,是一棵只有个点的树,我们要用它造出更多。
生成第 𝑖棵树我们需要五个参数 𝑎𝑖,𝑏𝑖,𝑐𝑖,𝑑𝑖,𝑙𝑖(𝑎𝑖,𝑏𝑖<𝑖)。我们生成第 。我们生成第 𝑖棵树是 将第 𝑎𝑖棵树的 𝑐𝑖号点和第 𝑏𝑖棵树的 𝑑𝑖号点用一条长度为 号点用一条长度为 号点用一条长度为 号点用一条长度为 号点用一条长度为 号点用一条长度为 号点用一条长度为 号点用一条长度为 𝑙𝑖的边连接起来形成新 的边连接起来形成新 的树 (不会改变原来两棵树 不会改变原来两棵树 不会改变原来两棵树 不会改变原来两棵树 )。下面我们需要对新树中的点重编号: )。下面我们需要对新树中的点重编号: )。下面我们需要对新树中的点重编号: )。下面我们需要对新树中的点重编号: )。下面我们需要对新树中的点重编号: )。下面我们需要对新树中的点重编号: )。下面我们需要对新树中的点重编号: 对于原来在 第𝑎𝑖棵树中的点 ,我们不会改变他的编号 ;对于原来在第 𝑏𝑖棵树中的点 ,我们 会将他们的编号加上第 𝑎𝑖棵树的点个数作为新编号 。
定义 𝐹(𝑇𝑖)=ΣΣ𝑑(𝑣𝑖,𝑣𝑗)𝑛−1𝑗=𝑖+1𝑛−1𝑖=0
其中 ,𝑛为树 𝑇𝑖的大小 ,𝑣𝑖,𝑣𝑗是𝑇𝑖中的 点, 𝑑(𝑣𝑖,𝑣𝑗)代表这两个点的距离。现 代表这两个点的距离。现 在希望你求出 ∀1≤𝑖≤𝑚,𝐹(𝑇𝑖)是多少 。
【输入格式】
第一行 一个整数 𝑚,代表要造多少棵树 。
接下来 𝑚行 ,每5个数 𝑎𝑖,𝑏𝑖,𝑐𝑖,𝑑𝑖,𝑙𝑖。
【输出格式】
𝑚行每一个整数代表 𝐹(𝑇𝑖)对109+7取模之后的值 。
【样例输入】
3
0 2
1 0 4
2 1 0 3
【样例输出】
2
28
216
【数据规模与约定】
对于 30%的数据, 1≤m≤10。
对于 60%的数据 ,每棵树的点数个不超过 105。
对于 100%的数据 ,1≤m≤60。
0
思路:30分建树后,暴力算。
60分线性做法,树形dp。?不会啊
三重dp。
两棵树并起来,只需算再算端点在两边的。
每个点 乘 右边树上总路程的和
为避免没必要的运算,开map,记忆化搜索,求需要的。
他竟然还想把longlong爆掉!