2021.9.20 CSP模拟赛总结+题解

2021.9.20 CSP模拟赛总结+题解

凑数2526

题目描述

 一个长度为n+m+k,包含n个数字2,m个数字5和k个数字6的序列,最多可能有多少个子序列是2526?
 如果一个序列是数组的子序列,当且仅当这个序列可以由数组删去任意个元素,再将数组中的剩余元素按顺序排列而成。

输入格式

 第一行一个整数t,表示测试用例的组数。
 接下来t行每行三个整数nm,k表示一组测试用例。

输出格式

 对于每组测试用例输出一行一个整数表示答案。

样例输入

 3
 6 7 8
 1 2 2
 6 0 3

样例输出

 504
 0
 0

数据范围与提示

1<=t<=200000 0<=n,m,k<=10000

思路

把n分成2份,即n/2

然后求排列

如下:

n*m*n*k

注意

n为奇数时其中一个n除完要加1

CODE

#include
using namespace std;
long long int n,m,k,tmp,ans,t,bj;
int main()
{
    cin>>t;
    for(int i=1;i<=t;i++)//多组测试数据
    {
        scanf("%lld%lld%lld",&n,&m,&k);
        tmp=n/2;
        n=n-tmp;//加1操作 因为tmp是n/2,那n-tmp就是已经n的一半,加1操作也有了
        ans=n*m*tmp*k;
        cout<

2021.9.20 CSP模拟赛总结+题解_第1张图片

总结

这题想思路的时候慢了点

但想到了就挺好做的

注意

一定比赛要检查程序

旁边的一位没检查程序,漏了换行

最小乘积

题目描述

 给你两个非负的整数L,R,在区间[L,R]中找两个不同的数,使得它们的乘积模2019最小,输出这个结果。

输入格式

 第一行两个整数L,R

输出格式

 一行,表示mod 2019的最小值。

输入样例1

 2020 2040

输出样例1

 2

输入样例2

 4 5

输出样例2

 20

数据范围与提示

0<=L<=R<=$10^9$

思路

要往2019的倍数去想

只要R-L>=2019那么就一定有2019的倍数,那么2019的倍数乘以任何数都可以被2019整除

那剩下的就暴力就好了

所以这题就变简单了

算出R-L,大于等于2019的话直接输出0,小于2019的话做暴力做法

虽然暴力的时间复杂都还是O($n^2$),但暴力只用处理2019以下的数据

怎么暴力就不说了 懂得都懂

CODE

#include
using namespace std;
long long int l,r,minn=2020;
int main()
{
    cin>>l>>r;
    if(r-l>=2019)//大于的情况
    {
        cout<<0;
        return 0;
    }
    for(long long  i=l;i<=r;i++)//由于数据较大,相乘要开long long 类型
    {
        for(long long  j=l;j<=r;j++)//暴力
        {
            if(i==j) continue;
            minn=min(i*j%2019,minn);
        }
    }
    cout<

2021.9.20 CSP模拟赛总结+题解_第2张图片

总结

这题思路就是倍数,但在coding的时候没有想到i,j要开long long ,所以痛失44分

雨水

题目描述

有n座山排成一个圆环,编号为1~n。两座山之间有一个水坝。第i座山和第i+1座山之间的水坝称为第i个水坝。因为山是环形的,第n+1座山也是第1座山。第n+1个水坝也是第1个水坝。如果第i座山降雨量为2Li,则它的降雨量会平均地分到相邻的两座水坝去。假设水坝的水全是由山上的降雨提供。现在给出每一座水坝收到的水量,问每座山的降雨量。n是奇数。

输入格式

第一行一个整数n 接下来第二行有n个整数,表示每座水坝的水量。

输出格式

输出一行,共有n个数,表示每座山的降雨量。

输入样例1

 3
 2 2 4

输出样例1

 4 0 4

思路

这题是一个二分的思路,mid枚举第一座山的降雨量的一半,通过暴力求出mid是否可行,可行就输出,mid小了则最后的水库1和水库n必有一水库水多了,mid大了着相反,这样求一个单调mid。

CODE

#include
using namespace std;
long long int waterku[200000],taxtwaterku[200000],n;
int check(long long int x)//检查mid值是否可行
{
    for(int i=1;i<=n;i++) taxtwaterku[i]=waterku[i];
    taxtwaterku[1]-=x;
    taxtwaterku[n]-=x;
    for(int i=2;i<=n;i++)
    {
        int u=min(taxtwaterku[i],taxtwaterku[i-1]);
        taxtwaterku[i]-=u;
        taxtwaterku[i-1]-=u;
    }
    int flag=1;
    for(int i=1;i<=n;i++)
    {
        if(taxtwaterku[i]>0) flag=0;
    }
    if(flag==1) return 1;
    else if(taxtwaterku[1]>0||taxtwaterku[n]>0) return 2;
    else return 3;
}
int out(long long int x)//输出把mid在枚举一遍
{
    for(int i=1;i<=n;i++) taxtwaterku[i]=waterku[i];
    taxtwaterku[1]-=x;
    taxtwaterku[n]-=x;
    cout<>n;
    for(int i=1;i<=n;i++)
    {
        cin>>waterku[i];
    }
    int l=0,r=max(waterku[1],waterku[n]);
    while(l<=r)//二分,这里是l<=r
    {
        long long int mid=(l+r)/2;
        int flag=check(mid);
        if(flag==1)
        {
            out(mid);
        }
        else if(flag==2)
            l=mid+1;
        else
            r=mid;
    }
}

2021.9.20 CSP模拟赛总结+题解_第3张图片

总结

这题挺简单的,可惜考试是没有想出来。想到了二分,但没有想到mid枚举什么。

染色

题目描述

有一棵树,包含n个点,n-1条边,第i条边的两个端点为ui,vi,现在你要对所有的点染色,你一共有K种颜色。染色要求符合以下条件:

- 对两个距离小于等于2的不同顶点,它们必须染成不一样的颜色。

问有多少种染色的方案。输出模$10^9+7$的结果。

输入格式

第一行两个数,表示N和K。 接下来有N-1行,每一行两个整数,表示一条边的两个端点。

输出格式

一个答案。

输入样例1

 4 3
 1 2
 2 3
 3 4

输出样例1

 6

数据范围与提示

1<=n,k<=$10^5$ 1<=$u_i$,$v_i$<=n

思路

DFS推导,一个节点的贡献量即为k-爸爸-兄弟,在把贡献相乘即可。

CODE

#include
using namespace std;
long long nex[1000000],a[1000000],p[1000000],num[1000000],bj[1000000],ans=1,cn,n,k;
int dfs(int x,int fa,int br)
{
    ans*=k-fa-br;//方案数
    ans%=1000000007;
    bj[x]=1;
    int t=0;
    for(int i=num[x];i;i=nex[i])
    {
        if(bj[a[i]]==1) continue;
        if(fa+1<=2)
        {
            dfs(a[i],fa+1,t);
        }
        else
        {
            dfs(a[i],fa,t);
        }
        t++;
    }
    
}
int main()
{
    cin>>n>>k;
    for(int i=1;i<=n-1;i++)
    {
        int u,v;
        cin>>u>>v;
        cn++;
        a[cn]=u;
        nex[cn]=num[v];
        num[v]=cn;
        cn++;
        a[cn]=v;
        nex[cn]=num[u];
        num[u]=cn;//链式前向星
    }
    dfs(1,0,0);
    cout<

2021.9.20 CSP模拟赛总结+题解_第4张图片

总结

这题要仔细思考每个点的贡献,再用排列法求解

全局总结

这次题目并不难,只是没有认真思考。

也没有进行结束检查,在考试范低级错误丢分是很严重的问题。

以后考试后30分钟要记得检查。

还要提升自己的思维和代码实践能力。

你可能感兴趣的:(bfs,算法,c++,二分查找,广度优先)