2018.8.15提高B组模拟考试

emmm...所以为什么出狱了还要做监狱的考试啊?

 

T1 题意简述:jzoj5195

 

Description

Input

Output

Data Constraint

 

   解题思路:dp。设dp[i][j]为用了i个弹珠,放进j个抽屉中的方案数。

             一开始我想到的dp转移方程是dp[i][j]=(k=1~i/j)dp[i-k][j-1]。

             然后我就兴致勃勃地交了上去,只拿了10分。凉凉。

             看题解说是和第二类斯特林数相似,好像没毛病。

             转移方程为dp{i}[j]=dp[i-1][j-1]+dp[i-j][j]。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#define MOD 998244353
#define ll long long
using namespace std;
ll n,m,ans,dp[5001][5001];
int main()
{
    scanf("%lld%lld",&n,&m);
    dp[0][0]=1;
    for(ll i=1;i<=n;i++)
        for(ll j=1;j<=min(i,m);j++)
            dp[i][j]=(dp[i-1][j-1]+dp[i-j][j])%MOD;
    printf("%lld\n",dp[n][m]%MOD);
    return 0;
}

 


 

T2 题意简述:jzoj5197

 

Description

Input

Output

Data Constraint

 

   解题思路:结论题。

             通过打表可以发现,当gcd(a,b)=a xor b时,a-b=gcd(a,b)=a xor b。

             因此只需枚举a-b的取值并计数即可。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
using namespace std;
int n,cnt[10000001];
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=10000000;i++)
        for(int j=i+i;j<=10000000;j+=i)
            if((j^(j-i))==i) cnt[j]++;
    for(int i=1;i<=10000000;i++) cnt[i]+=cnt[i-1];
    printf("%d\n",cnt[n]);
    return 0;
}

 


 

T3 题意简述:jzoj5196

 

Description

Input

Output

Data Constraint

 

   解题思路:点分治。

             一遍点分治计算出所有(S,E)取值范围内的路径,计算时更新答案即可。

             注意dis数组不必memset,也不必sort,否则会T得很惨。

#pragma GCC optimize(3)
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<set>
#define INF 0x3f3f3f3f
using namespace std;
set<int> st;
int n,ans=INF,sta,end,cnt,head[100001];
int mn,root,siz[100001],vis[100001],dis[100001],tot;
struct uio{
    int nxt,to,val;
}edge[200001];
void add(int x,int y,int z)
{
    edge[++cnt].nxt=head[x];
    edge[cnt].to=y;
    edge[cnt].val=z;
    head[x]=cnt;
}
void getroot(int x,int fa,int size)
{
    siz[x]=1;
    int tmp=0;
    for(int i=head[x];i;i=edge[i].nxt)
    {
        int y=edge[i].to;
        if(y==fa||vis[y]) continue;
        getroot(y,x,size);
        siz[x]+=siz[y];
        tmp=max(tmp,siz[y]);
    }
    tmp=max(tmp,size-siz[x]);
    if(tmp<mn) mn=tmp,root=x;
}
void getdis(int x,int fa,int len)
{
    dis[++tot]=len;
    for(int i=head[x];i;i=edge[i].nxt)
    {
        int y=edge[i].to;
        if(y==fa||vis[y]) continue;
        getdis(y,x,len+edge[i].val);
    }
}
void dfs(int x)
{
    vis[x]=1;
    st.clear();
    st.insert(INF);
    for(int i=head[x];i;i=edge[i].nxt)
    {
        int y=edge[i].to;
        if(vis[y]) continue;
        tot=0;
        getdis(y,x,edge[i].val);
        for(int j=tot;j;j--)
        {
            int tmp=*st.lower_bound(sta-dis[j]);
            tmp+=dis[j];
            if(tmp<ans&&tmp>=sta&&tmp<=end) ans=tmp;
        }
        for(int j=tot;j;j--)
        {
            if(dis[j]<ans&&dis[j]>=sta&&dis[j]<=end) ans=dis[j];
            st.insert(dis[j]);
        }
    }
    for(int i=head[x];i;i=edge[i].nxt)
    {
        int y=edge[i].to;
        if(vis[y]) continue;
        mn=INF,getroot(y,0,siz[y]);
        dfs(root);
    }
}
int main()
{
    scanf("%d%d%d",&n,&sta,&end);
    for(int i=1;i<n;i++)
    {
        int u,v,w;
        scanf("%d%d%d",&u,&v,&w);
        add(u,v,w),add(v,u,w);
    }
    mn=INF,getroot(1,0,n);
    dfs(root);
    if(ans==INF) printf("-1\n");
    else printf("%d\n",ans);
    return 0;
}

 

posted @ 2018-08-16 08:41  radishえらい  阅读(113)  评论(0编辑  收藏  举报