2019长沙学院新生赛题解

题目链接

A:打表找规律,发现每四个数就是0,所以找第一个大于l的四的倍数,找第一个小于r的四的倍数,然后异或。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
int main ()
{
    int T;
    cin>>T;
    while(T--)
    {
        long long l,r,p=0,o=0,y,x;
        cin>>l>>r;
        if(r-l<=4)
        {
            for(ll i=l;i<=r;i++)p^=i;
            printf("%lld\n",p);
            continue;
        }
        ll tt=0;
        y=4-l%4+l,x=r-r%4;
        for(ll i=l;i<y;i++)p^=i;
        for(ll i=x;i<=r;i++)o^=i;
        ll ans=p^o;
        cout<<ans<<'\n';
     }
      
}

C:整除分块,把多项式拆分,然后整除分块,需要用到的公式:

\large \sum \left ( n mod \right i )= \sum \left ( n \left -[ n/i \right ] \right )

\large 1^{2}+2^{2}+...+n^{2} = n*(n+1)*(2*n+1)/6

\large 1^{3}+2^{3}+...+n^{3}=((n+1)/2)^{2}

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll mod = 1e9+7;
ll ksm(ll a,ll b)
{
    ll ans=1;
    while(b)
    {
        if(b&1)ans = ans*a%mod;
        a=a*a%mod;
        b/=2;
    }
    return ans%mod;
}
ll nn(ll n)
{
    return ksm(n,mod-2);
}


ll cur1(ll n)
{
    return n*(n+1)%mod*(2*n+1)%mod*nn(1ll*6)%mod;
}

ll cur2(ll n)
{
    return ksm((n+1),2)*nn(1ll*4)%mod*ksm(n,2)%mod;
}

int main()
{
    ll n,m;
    cin>>n>>m;
    ll ans=0;
    for(ll l=1,r;l<=n;l=r+1)
    {
        r=n/(n/l);
        ans=(ans + (cur2(r)-cur2(l-1)+mod)%mod * (n/l)% mod )%mod;
    }
    ans = (n*cur1(n)%mod - ans +mod)%mod;

    ll ans1=0;
    for(ll l=1,r;l<=m;l=r+1)
    {
        r=m/(m/l);
        ans1=(ans1 + (cur1(r)-cur1(l-1) + mod)%mod * (m/l)%mod)%mod;
    }
    ans1=((1+m)*m%mod*m%mod*nn(1ll*2)%mod-ans1  + mod)%mod;
    cout<<ans1*ans%mod<<'\n';
}

 c:把每个数二进制拆分,用一个数组保存1的个数,让m尽可能小的选择每一位是0还是1,如果此时的异或和还是大于输出-1,否则看是否能把之前选的0变成1,输出答案。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll a[1005],mn[55],p[55],t[55];
int main ()
{
    ll n,m;
    cin>>n>>m;
    p[0]=1;
    ll sum=0;
    for(int i=1;i<=50;i++)
        p[i]=p[i-1]*2;
         
         
    for(int i=1;i<=n;i++)scanf("%lld",a+i);
     
    for(int i=0;i<=50;i++)
    {
        int x=0;
        for(int j=1;j<=n;j++)
        {
            if((a[j]>>i)&1)
            {
                x++;
            }
        }
        if(n-x>x)
        {
            t[i]=x;
            mn[i]=0;
            sum+=p[i]*(x);
        }
        else
        {
            t[i]=n-x;
            mn[i]=1;
            sum+=p[i]*(n-x);
        }
    }
    if(sum>m)puts("-1");
    ll _sum=sum,ans=0;
    for(int i=50;i>=0;i--)
    {
        _sum-=p[i]*t[i];
         
        if(mn[i]==0)
        {
            ll w=p[i]*(n-t[i]);
            if(ans+w+_sum<m)
            {
                ans+=w;
                mn[i]=1;
            }
            else ans+=p[i]*t[i];
        }
        else ans+=p[i]*t[i];
    }
    ans=0;
    for(int i=0;i<=50;i++)
    {
        if(mn[i])ans+=p[i];
    }
    cout<<ans<<'\n';
    return 0;
}

 F 待补

H:换根dp,d表示最远点的距离,f代表最远点的个数,答案就等于f相加,ans要开ll。

#include<bits/stdc++.h>
using namespace std;
const int maxn=3e5+100;
#define pi pair<int,int>
#define mk make_pair
#define ll long long
vector<int>G[maxn];
int d[maxn],f[maxn];
vector<pi>pre[maxn];
void dfs(int u,int fa)
{
    d[u]=0,f[u]=1;
    for(auto v : G[u])
    {
        if(v==fa)continue;
        dfs(v,u);
        if(d[u]==d[v]+1)
        {
            f[u] += f[v];
        }
        else if(d[v]+1>d[u])
        {
            f[u] = f[v];
            d[u]=d[v]+1;
        }
    }
}
ll mx=0,ans=0;
 
void dfs1(int u,int fa)
{
    pre[u].push_back(mk(0,1));
    pi cnt = pi(0,1);
    d[u]=0,f[u]=1;
    for(auto v : G[u])
    {
        if(d[u]==d[v]+1)
        {
            f[u] += f[v];
            //cnt.second =f[u];
        }
        else if(d[v]+1>d[u])
        {
            f[u]=f[v];
            d[u]=d[v]+1;
            //cnt=mk(d[u],f[u]);
        }
        pre[u].push_back(mk(d[u],f[u]));
    }
    if (d[u] == ans)
        mx += f[u];
    else if(d[u]>ans)
    {
        mx=f[u];
        ans=d[u];
    }
    pi la=mk(0,0);
    for(int i=G[u].size()-1;i>=0;i--)
    {
        if(pre[u][i].first==la.first)
        {
            d[u]=pre[u][i].first;
            f[u] = pre[u][i].second + la.second;
        }
        else
        {
            if(pre[u][i].first>la.first)
            {
                d[u]=pre[u][i].first;
                f[u] = pre[u][i].second;
            }
            else
            {
                d[u]=la.first;
                f[u] = la.second;
            }
        }
        if(d[G[u][i]]+1 == la.first)
            la.second += f[G[u][i]];
        if(d[G[u][i]] + 1 >la.first)
            la.first=d[G[u][i]]+1,la.second = f[G[u][i]];
        if(G[u][i]!=fa)
         dfs1(G[u][i],u);
    }
}
int main()
{
    int n,u,v;
    scanf("%d",&n);
    for(int i=1;i<n;i++)
    {
        scanf("%d%d",&u,&v);
        G[u].push_back(v);
        G[v].push_back(u);
    }
    dfs(1,0);
    dfs1(1,0);
    cout<<mx<<'\n';
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值