11月04日解题报告

考试思路

今天考试情况不好,策略上还存在问题,内存定义的问题又出现了,看来还是不能放松啊,第一题没有开long long 直接从80掉到20,第二题超内存本来可以搞到的35分直接爆0,啊~本来可以有100多分的,看来还是自己能力有欠缺啊,还是要多多向大佬学习,好好改正才是,至于解题策略,还是要力求第一题要稳才是,太大意只会1分没有

第一题

题面
定义”组合数”S(n,m)代表将 n 个不同的元素拆分成 m 个非空集合的方案数.举个栗子,将{1,2,3}拆分成 2 个集合有({1},{2,3}),({2},{1,3}),({3},{1,2})三种拆分方法.
小猫想知道,如果给定 n,m 和 k,对于所有的 0<=i<=n,0<=j<=min(i,m),有多少对(i,j),满足 S(i,j)是 k 的倍数.
注意,0 也是 k 的倍数,S(0,0)=1,对于 i>=1,S(i,0)=0.
输入格式
从 problem.in 种读入数据
第一行有两个整数 t,k,t 代表该测试点总共有多少组测试数据.
接下来 t 行,每行两个整数 n,m.
输出格式
输出到文件 problem.out 中t 行,每行一个整数代表所有的 0<=i<=n,0<=j<=min(i,m),有多少对(i,j),满足 S(i,j)是 k 的倍数.
样例输入 1
1 2
3 3
样例输出 1
3
AC思路
这道题其实思路比较简单,方程也比较好推,s(i,j)=s(i-1,j-1)+s(i-1,j)*j,然而没有发现数据会爆long long 忘记对K随时取%,于是。。。唉,然后如果纯暴力是会T掉2个点的,要处理一个前缀和才行
代码

#include<iostream>
#include<cstdio>
using namespace std;
long long t,k;
long long xuan[3000][3000];
long long fan[3000][3000];
long long ans=0;
int main()
{
    //freopen("problem.in","r",stdin);
    //freopen("problem.out","w",stdout);
    scanf("%lld%lld",&t,&k);
    xuan[0][0]=1;
    for(int i=1;i<=2000;i++)
        for(int j=1;j<=i;j++)
        {
           xuan[i][j]=(xuan[i-1][j-1]+xuan[i-1][j]*j)%k;
        }
     fan[0][0]=1;
     for(int i=1;i<=2000;i++)
     { 
        ans=0;
        for(int j=0;j<=2000;j++)
        {
            if(j<=i&&xuan[i][j]==0)
                ans++;
            fan[i][j]=fan[i-1][j]+ans;
        }
     } 
    for(long long i=1;i<=t;i++)
    {
        long long a,b;
        scanf("%lld%lld",&a,&b);
        cout<<fan[a][b]<<endl;
    }
}

第二题

题面
信息组最近猫成灾了!隔壁物理组也拿猫没办法.信息组组长只好去请神刀手
来帮他们消灭猫.
信息组现在共有 n 只猫(n 为正整数),编号为 1 到 n,站成了一个环,第 i 只猫的左边是第i-1 只猫,右边是第 i+1 只猫.特别的,第 1 只猫的左边是第 n 只猫,第 n 只猫的右边是第 1只猫.每只猫拥有价值,表示消灭它能给信息组组长带来的声誉.
注意,有的猫价值为负数,这意味着消灭它会损害组长的声誉.
神刀手可以选择一些猫消灭掉.但是,我们的组长实际上非常喜欢猫,他希望神刀手不要消灭两只相邻的猫.
神刀手的能力组长现在还不知道.所以,组长希望知道对于所有的 1<=m<=n/2,如果神刀手刚好消灭 m 只猫,他最多能获得的声誉.
信息组组长当然知道怎么做啦!但是他想考考你……
输入格式
从 cat.in 中读入数据
第一行包括一个正整数 n
第二行为 n 个整数,依次代表第 1,2,…,n 只猫的价值.
输出格式
输出到文件 cat.out
输出共 n/2 行,第 i 行表示假如神刀手刚好消灭 i 只猫,信息组组长最多能获得
的收益.
样例输入1
8
1 1 8 1 1 9 1 1
样例输出1
9
17
18
12
AC思路
假如消灭某一只猫的收益大于与它相邻的两只猫的收益时,那么假如不消灭这一只猫,就一定要消灭与它相邻的两只猫。所以我们可以强制消灭这一只猫,并把相邻的与它两只猫缩成一只猫,权值为相邻的那两只猫的收益和-这只猫的收益。发现,假如再消灭缩出来的那只猫,那么收益就相当于只消灭相邻的猫的收益,并且消灭的猫数增加 1.发现这时候原问题转化成了 n-2,m-1 规模的子问题。
于是,我们每次可以消灭所有猫中收益最高的那只猫,并把与它相邻的猫缩起来即可。因为最优解一定满足前面的性质,所以可以这么贪心地做。
代码

#include<iostream>
#include<cstdio>
#include<queue>
using namespace std;
long long n;
long long h[405000];
long long ans=0;
long long las[400500];
long long nex[400500];
long long num=0;
long long vis[400500];
struct node
{
    long long biao;
    long long jia;
};
bool operator < (const node &a,const node &b){
    return a.jia<b.jia;
}//重载运算符
priority_queue<node>q;
int main()
{
    scanf("%lld",&n);
    long long m=n/2;
    for(long long i=1;i<=n;i++)
    {
        cin>>h[i];
        if(i==1)las[i]=n;
        else las[i]=i-1;
        if(i==n)nex[i]=1;
        else nex[i]=i+1;
        node l;
        l.biao=i;
        l.jia=h[i];
        q.push(l);
    }
    num=n;
    node st;
    for(long long i=1;i<=m;i++)
    {
        st=q.top();
        q.pop();
        while(!q.empty()&&vis[st.biao])//找到没有消灭的
        {
            st=q.top();
            q.pop();
        }
        ans+=st.jia;//消灭最大声誉的猫
        vis[st.biao]=1;//消灭完了;
        vis[nex[st.biao]]=1,vis[las[st.biao]]=1;
        num++;
        h[num]=h[las[st.biao]]+h[nex[st.biao]]-h[st.biao];//把前后两只猫合并为一只,存入利润差;
        nex[num]=nex[nex[st.biao]],las[nex[num]]=num;
        las[num]=las[las[st.biao]],nex[las[num]]=num;
        node l;
        l.jia=h[num];
        l.biao=num;
        q.push(l);
        printf("%lld\n",ans);
    }   
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值