noip模拟66[依旧很菜]
noip模拟66 solutions
话说这几次一直改不完题,今天也只是改了三道题
只能先咕掉,以后再改了。。
今天的考试,时间分配极其不好,还有一个就是我思想的问题
做到最后发现啥也不会,然后就不想做了,导致我直接交了前两个题就走人了
以后一定要做完题,要不然会非常后悔的
T1 接力比赛
这个我知道是个背包,但是我直接干了个裸的上去,一点优化都没带
然后导致我没有切掉,,,
下次遇见题一定要记得优化暴力
AC_code
#include<bits/stdc++.h>
using namespace std;
#define oj
#define int long long
#define fo(i,x,y) for(int i=(x);i<=(y);i++)
#define fu(i,x,y) for(int i=(x);i>=(y);i--)
const int N=1005;
const int M=1e6;
int n,m,tot,ans;
int wn[N],vn[N],sn[N];
int wm[N],vm[N],sm[N];
int f[M],g[M];
signed main(){
#ifdef oj
freopen("game.in","r",stdin);
freopen("game.out","w",stdout);
#endif
scanf("%lld%lld",&n,&m);
fo(i,1,n)scanf("%lld%lld",&wn[i],&vn[i]),sn[i]=sn[i-1]+wn[i];
fo(i,1,m)scanf("%lld%lld",&wm[i],&vm[i]),sm[i]=sm[i-1]+wm[i];
memset(f,-0x3f,sizeof(f));f[0]=0;
memset(g,-0x3f,sizeof(g));g[0]=0;
fo(i,1,n)fu(j,sn[i],wn[i])f[j]=max(f[j],f[j-wn[i]]+vn[i]);
fo(i,1,m)fu(j,sm[i],wm[i])g[j]=max(g[j],g[j-wm[i]]+vm[i]);
fo(i,1,min(sn[n],sm[m]))ans=max(ans,f[i]+g[i]);
printf("%lld",ans);
}
T2 树上竞技
这个题太妙了,那个组合数!!!
其实对于许多组合数来说,当你给他赋予一个实际含义的时候,
如果需要递推,或者需要求和,这样就会变得很简单
所以要不断地积累一些例子,让在考场上应用组合数的时候更加得心应手
AC_code
#include<bits/stdc++.h>
using namespace std;
#define oj
#define int long long
#define fo(i,x,y) for(int i=(x);i<=(y);i++)
#define fu(i,x,y) for(int i=(x);i>=(y);i--)
const int N=1e6+5;
const int mod=1e9+7;
int n,m;
int to[N*2],nxt[N*2],head[N],rp;
void add_edg(int x,int y){
to[++rp]=y;
nxt[rp]=head[x];
head[x]=rp;
}
int g[N],jc[N],inv[N];
int ksm(int x,int y){
int ret=1;
while(y){
if(y&1)ret=ret*x%mod;
x=x*x%mod;y>>=1;
}return ret;
}
int C(int x,int y){if(x<y)return 0;return jc[x]*inv[y]%mod*inv[x-y]%mod;}
int siz[N],ans;
void dfs(int x,int f){
siz[x]=1;
for(int i=head[x];i;i=nxt[i]){
int y=to[i];
if(y==f)continue;
dfs(y,x);siz[x]+=siz[y];
}
ans=(ans+g[siz[x]]+g[n-siz[x]])%mod;
if(m%2==0)ans=(ans+C(siz[x],m/2)*C(n-siz[x],m/2)%mod*(m/2)%mod)%mod;
}
signed main(){
#ifdef oj
freopen("meeting.in","r",stdin);
freopen("meeting.out","w",stdout);
#endif
scanf("%lld%lld",&n,&m);
fo(i,2,n){
int x;scanf("%lld",&x);
add_edg(i,x);add_edg(x,i);
}
jc[0]=1;fo(i,1,n)jc[i]=jc[i-1]*i%mod;
inv[0]=1;inv[n]=ksm(jc[n],mod-2);
fu(i,n-1,1)inv[i]=inv[i+1]*(i+1)%mod;
if(m>2)g[1]=C(n-1,m-1);
fo(i,1,n-1)g[i+1]=(g[i]+mod-C(i-1,(m-1)/2-1)*C(n-i-1,m-(m-1)/2-1)%mod)%mod;
fo(i,1,n)g[i]=g[i]*i%mod;
dfs(1,0);printf("%lld",ans);
}
T3 虚构推理
有一点点小小的后悔。
这道题我考场上看到非常的麻烦,就直接跳过了
但是后来一看好像还挺简单的,暴力分还是挺好拿的
我没有打正解,直接在时间复杂度可以接受的范围内枚举的
AC_code
#include<bits/stdc++.h>
using namespace std;
#define oj
#define fo(i,x,y) for(int i=(x);i<=(y);i++)
#define fu(i,x,y) for(int i=(x);i>=(y);i--)
const int N=50005;
int n,ah,am,as;
double h[N],m[N],ans=1000000000.0;
void sol(double i,double j,double k){
double th=i*30.0+j*0.5+k*0.5/60.0;
double tm=j*6.0+k*0.1;
if(th>=180.0)th-=180.0;
else th+=180.0;
if(tm>=180.0)tm-=180.0;
else tm+=180.0;
int ph=upper_bound(h+1,h+n+1,th)-h-1;
int pm=upper_bound(m+1,m+n+1,tm)-m-1;
double r1=180.0-th+h[ph];if(r1<0)r1+=360.0;if(r1>=360.0)r1-=360.0;
double r2=180.0-h[ph+1]+th;if(r2<0)r2+=360.0;if(r2>=360.0)r2-=360.0;
double r3=180.0-tm+m[pm];if(r3<0)r3+=360.0;if(r3>=360.0)r3-=360.0;
double r4=180.0-m[pm+1]+tm;if(r4<0)r4+=360.0;if(r4>=360.0)r4-=360.0;
if(360.0-r1<r1)r1=360.0-r1;
if(360.0-r3<r3)r3=360.0-r3;
ans=min(ans,max(max(r1,r2),max(r3,r4)));
}
signed main(){
#ifdef oj
freopen("unreal.in","r",stdin);
freopen("unreal.out","w",stdout);
#endif
scanf("%d",&n);
fo(i,1,n){
scanf("%d",&ah);getchar();
scanf("%d",&am);getchar();
scanf("%d",&as);getchar();ah%=12;
//cout<<ah<<":"<<am<<":"<<as<<endl;
h[i]=ah*30.0+am*0.5+as*0.5/60.0;
m[i]=am*6.0+as*0.1;
}
sort(h+1,h+n+1);h[0]=h[n];h[n+1]=h[1];
sort(m+1,m+n+1);m[0]=m[n];m[n+1]=m[1];
fo(i,0,11)fo(j,0,59)for(double k=0;k<60;k+=0.01)sol(i,j,k);
printf("%.10lf",ans);
}
T4 记忆碎片
//我还没有改
改完啦改完啦----10.08
这个\(dp\)确实是妙哉
首先我们对于这个图一无所知,但是我们知道一些在最小生成树上的边
这个就给了我们一个限制,我们从小到大一条一条边的加入图中
如果当前加入的不是树边,那么这个边只能连接两个在同一连通块中的点
如果是树边,就必须连接两个连通块!!!
这样我们先预处理这张图中可能会出现的连通性的种类,也就是对于\(n\)的整数划分
然后用\(map\)映射到一个数上,对于这个东西\(dp\)并转移
AC_code
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define fxt(i,x,y) for(int i=(x);i<=(y);i++)
#define pyt(i,x,y) for(int i=(x);i>=(y);i--)
const int N=45;
const int M=45*45;
const int T=45*45*20;
const int mod=1e9+7;
int n,m,knd,f[M][M*40],e[M*20];
bool vis[M];
vector<int> s[M*20],v;
map<vector<int>,int> mp;
void dfs(int l,int r){
if(!r){
s[++knd]=v;mp.insert(make_pair(v,knd));
fxt(i,0,(int)v.size()-1)e[knd]+=v[i]*(v[i]-1)/2;
return ;
}
if(r<l)return ;
fxt(i,l,r){
v.push_back(i);
dfs(i,r-i);
v.pop_back();
}
}
signed main(){
freopen("tree.in","r",stdin);
freopen("tree.out","w",stdout);
scanf("%lld",&n);
m=n*(n-1)/2;
fxt(i,1,n-1){
int x;scanf("%lld",&x);
vis[x]=true;
}
dfs(1,n);f[0][1]=1;
fxt(i,1,m){
fxt(j,1,knd){
if(!f[i-1][j])continue;
if(!vis[i]){
f[i][j]=(f[i][j]+f[i-1][j]*(e[j]-i+1))%mod;
continue;
}
fxt(x,0,(int)s[j].size()-1){
fxt(y,x+1,(int)s[j].size()-1){
vector<int> tmp;tmp.clear();
tmp.push_back(s[j][x]+s[j][y]);
fxt(k,0,(int)s[j].size()-1)
if(k!=x&&k!=y)tmp.push_back(s[j][k]);
sort(tmp.begin(),tmp.end());
int pos=mp.find(tmp)->second;
f[i][pos]=(f[i][pos]+f[i-1][j]*s[j][x]%mod*s[j][y]%mod)%mod;
}
}
}
}
printf("%lld",f[m][knd]);
}
QQ:2953174821