Codeforces Round #654 (Div. 2) (A-E2)

题目:A. Magical Sticks
题意:在[1,n]范围内能最多能连接出多少根相同的棒子。

1和n-1相互连接,类推。

#include<cmath>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cstdlib>
#include<istream>
#include<vector>
#include<stack>
#include<set>
#include<map>
#include<algorithm>
#include<queue>
#define inf 0x3f3f3f3f
#define llinf 0x3f3f3f3f3f3f3f3f
#define MAX_len 200005*4
using namespace std;
typedef long long ll;
typedef pair<int,int> PP;
const int mod=998244353;
const int MAXlen=1e5+10;
long double eps=1e-9;
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int n;
        scanf("%d",&n);
        if(n&1)
            n=n/2+1;
        else
            n/=2;
        printf("%d\n",n);
    }
    return 0;
}

题目:B. Magical Calendar
题意:一周的天数可为[1,k] (一行的格子数),在日历上连续涂色n天,并且每个格子都要有可以连接的,如过通过平移可以重叠则为1种情况。
我读的不是很清楚大致意思。

分情况讨论n>r时,1+2+…+r;
其余即1+2+3+…+n-1+1,画画图好理解。

#include<cmath>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cstdlib>
#include<istream>
#include<vector>
#include<stack>
#include<set>
#include<map>
#include<algorithm>
#include<queue>
#define inf 0x3f3f3f3f
#define llinf 0x3f3f3f3f3f3f3f3f
#define MAX_len 200005*4
using namespace std;
typedef long long ll;
typedef pair<int,int> PP;
const int mod=998244353;
const int MAXlen=1e5+10;
long double eps=1e-9;
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        ll n,r;
        scanf("%lld %lld",&n,&r);
        ll temp;
        if(n>r)
        {
            temp=r*(r+1)/2;
        }
        else
        {
            temp=n*(n-1)/2+1;
        }
        printf("%lld\n",temp);
    }
    return 0;
}

C. A Cookie for You
题意:a,b块香草和巧克力饼干,有两类客人按规律来吃,没得吃就生气,你可以安排来的顺序,问会不会导致生气(尽量不让生气)。

按照大类来看就是,第二类客人就吃少的饼干(相等就吃香草),第一类就吃多的(相等就吃巧克力),总的来说就是这样,(n+m>a+b)肯定失败,可知m<=min(a,b)时一定成功,第一类可以一直吃下去。当m>min(a,b)时,要平衡必须让第二类去吃多的,但是第一类客人把a,b吃的相等了再让第二类去吃多的那种,只能吃一次,代价是第一类去吃少的显然不行。

#include<cmath>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cstdlib>
#include<istream>
#include<vector>
#include<stack>
#include<set>
#include<map>
#include<algorithm>
#include<queue>
#define inf 0x3f3f3f3f
#define llinf 0x3f3f3f3f3f3f3f3f
#define MAX_len 200005*4
using namespace std;
typedef long long ll;
typedef pair<int,int> PP;
const int mod=998244353;
const int MAXlen=1e5+10;
long double eps=1e-9;
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        ll a,b,n,m;
        scanf("%lld %lld %lld %lld",&a,&b,&n,&m);
        if(n+m>a+b)
        {
            printf("No\n");
            continue;
        }
        if(m<=min(a,b))
        {
            printf("Yes\n");
        }
        else
            printf("No\n");
    }
    return 0;
}

题目:D. Grid-00100

题意:在这里插入图片描述

找到1最多的行减最少的行的平方+同理列,这个值的最小值。

分析放的过程,先放1一个在左上角,对第一行贡献+1,第一列贡献+1,继续放就不能再放同一行同一列,这样就扩大了这一行或者这一列的贡献值,增大了结果。所以放下一行下一列,依次类推。

#include<cmath>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cstdlib>
#include<istream>
#include<vector>
#include<stack>
#include<set>
#include<map>
#include<algorithm>
#include<queue>
#define inf 0x3f3f3f3f
#define llinf 0x3f3f3f3f3f3f3f3f
#define MAX_len 200005*4
using namespace std;
typedef long long ll;
typedef pair<int,int> PP;
const int mod=998244353;
const int MAXlen=1e5+10;
long double eps=1e-9;
int a[310][310];
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        memset(a,0,sizeof(a));
        int n,k,i,j;
        scanf("%d %d",&n,&k);
        if(k%n==0)
        {
            i=j=0;
            int sum=0;
            int hh=0;
            while(sum<k)
            {
                a[(i)%n][(j+hh)%n]=1;
                sum++;
                i++;
                j++;
                if(sum%n==0)
                {
                    hh++;
                }
            }
            printf("0\n");
            for(i=0;i<n;i++)
            {
                for(j=0;j<n;j++)
                {
                    printf("%d",a[i][j]);
                }
                printf("\n");
            }
            continue;
        }
        printf("2\n");
        i=j=0;
            int sum=0;
            int hh=0;
            while(sum<k)
            {
                a[(i)%n][(j+hh)%n]=1;
                sum++;
                i++;
                j++;
                if(sum%n==0)
                {
                    hh++;
                }
            }
 
            for(i=0;i<n;i++)
            {
                for(j=0;j<n;j++)
                {
                    printf("%d",a[i][j]);
                }
                printf("\n");
            }
    }
    return 0;
}

题目:E1. Asterism (Easy Version)

题意:给定n个数的数组,表示怪物i有a[i]个糖果,你初始x个糖果,x>=a[i]则可以击败怪物并且糖果个数+1,f(x)为击败所有怪物的顺序方式的种类数,并且f(x)与p互质。输出可能的x,以及x的数量。

首先分析最小值显然是从小到大排列完依次打过去都可以赢。
我们sort数组,去枚举x的初始值,判断成功否,以及f(x)是否%p==0,存起来。f(x)怎么计算,小于x的个数是y的话,显然有y!,前y个的方式则为y!,a[y+1]大于x的时候,x要补充a[y+1]-x的值,那么f(x)=y!*(a[y+1]可以存在的位置的可能个数)即为前y+1个的情况,类推。

#include<cmath>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cstdlib>
#include<istream>
#include<vector>
#include<stack>
#include<set>
#include<map>
#include<algorithm>
#include<queue>
#define inf 0x3f3f3f3f
#define llinf 0x3f3f3f3f3f3f3f3f
#define MAX_len 200005*4
using namespace std;
typedef long long ll;
typedef pair<int,int> PP;
const int mod=998244353;
const int MAXlen=1e5+10;
long double eps=1e-9;
int a[2020];
int ans[2020];
int main()
{
    int len=0;
    int n,p,i,j;
    scanf("%d %d",&n,&p);
    int MAX=0;
    for(i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
        MAX=max(MAX,a[i]);
    }
    sort(a+1,a+1+n);
    for(i=1;i<MAX;i++)
    {
        if(a[1]>i)
            continue;
        int temp=upper_bound(a+1,a+1+n,i)-a;
        temp--;
        if(temp>=p)
            continue;
        ll sum=1;
        for(j=1;j<=temp;j++)
        {
            sum=(1ll*j*sum)%p;
        }
        if(!sum)
        continue;
        bool flag=true;
        int hhu=i;
        for(j=1;j<=n;j++)
        {
            if(hhu>=a[j])
            {
                hhu++;
                continue;
            }
            else
            {
                flag=false;
                break;
            }
        }
        if(flag)
        {
            for(j=temp+1;j<=n;j++)
            {
                int tmp=a[j]-i;
                sum=(1ll*(j-a[j]+i)*sum)%p;
            }
            if(!sum)
                continue;
            else
            {
                ans[++len]=i;
            }
        }
    }
    printf("%d\n",len);
    for(i=1;i<=len;i++)
        printf("%d ",ans[i]);
    return 0;
}

题目:E2. Asterism (Hard Version)

题意和E1一样,n,p范围变了,到1e5。

分析x一定满足x+i-1>=a[i],我们找到这个下界枚举x>=(a[i]+1-i),f(x)是单调的,计算式子为sum=(1ll*(j-a[j]+x)*sum)%p,x变大sum变大,y!可能也变大,所以找到f(x)成立,f(x+1)不成立的临界点x,如果f(x)%p=0,那么f(x+1)也是%p=0的,那么就二分去找x的上界。

#include<cmath>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cstdlib>
#include<istream>
#include<vector>
#include<stack>
#include<set>
#include<map>
#include<algorithm>
#include<queue>
#define inf 0x3f3f3f3f
#define llinf 0x3f3f3f3f3f3f3f3f
#define MAX_len 200005*4
using namespace std;
typedef long long ll;
typedef pair<int,int> PP;
const int mod=998244353;
const int MAXlen=1e5+10;
long double eps=1e-9;
int a[100100];
int main()
{
    int len=0;
    int n,p,i,j;
    scanf("%d %d",&n,&p);
    int MAX=0;
    for(i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
        MAX=max(MAX,a[i]);
    }
    int MIN=0;
    sort(a+1,a+1+n);
    for(i=1;i<=n;i++)
    {
        MIN=max(MIN,a[i]-i+1);
    }
    int l=MIN,r=MAX;
    int hh=-1;
    int mid;
    while(l<=r)
    {
        mid=(l+r)>>1;
        int hhu=mid;
        ll aa=1;
        int sum=0;
        bool flag=true;
        if(a[1]>mid)
        {
            l=mid+1;
            continue;
        }
        for(j=1;j<=n;j++)
        {
            if(hhu<a[j])
            {
                break;
            }
            else
                sum++;
        }
        for(i=1;i<=sum;i++)
        {
            aa=(1ll*i*aa)%p;
        }
        for(;j<=n;j++)
        {
            int tmp=a[j]-hhu;
            aa=(1ll*(j-a[j]+hhu)*aa)%p;
        }
        if(!aa)
        {
            hh=mid;
            r=mid-1;
        }
        else
            l=mid+1;
    }
    if(hh<=MIN)
    {
        printf("0\n");
        return 0;
    }
    printf("%d\n",hh-MIN);
    for(i=MIN;i<hh;i++)
    {
        printf("%d ",i);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_43958964/article/details/107434954