2020 CCPC长春L Coordinate Paper (思维构造)

  • 比赛的时候榜带偏了,导致L没开出来,当时思路想的挺对了,但觉得好像不是很对,最后没尝试,最后三题遗憾铜牌第二。今天补出来了。。。
    题意很清晰,让你构造一个n的序列,要么ai=ai-1+1;
    要么ai=a[i-1]-k。和为S,首先我们去想什么时候不行,也就是构造这个序列的最小值,一定是0123…k0123…k这样构造,而且这个最小值可以用前缀和计算得出,而且很关键的一个地方就是,我们构造的这个和最小的系列,可以通过整体都加(k+1)的倍数,或某个可以增加k+1,而且对于k来说,我们以开头构造的序列的和可以包括到所有%(k+1)的情况,比如4 2 11:
    构造开头: 0120 和为3%3=0  11%3=2 1201   4   1 2012   5   2
    所以2012 可以构造出11的和,11-5=6  6/(k+1)=2 所以将两个数+(k+1)即可。总复杂度接近O(k+n);
    而且最后加的时候我是直接暴力加的,57ms。
在这里插入代码片
#pragma GCC optimize(3)
#include <bits/stdc++.h>
#define debug(x) cout<<#x<<":"<<x<<endl;
#define _CRT_SECURE_NO_WARNINGS
typedef  long long ll;
using namespace std;
#define rep(i,j,n) for(ll i=j;i<=n;i++)
#define per(i,j,n) for(ll i=j;i>=n;i--)
typedef unsigned long long ull;
typedef unsigned short us;
const ll INF= 1e18+7;
const ll maxx = 1e6+7;
const ll mod= 1e9+7;
const double eps=1e-8;
inline bool read(ll &num){char in;bool IsN=false;in=getchar();if(in==EOF) return false;while(in!='-'&&(in<'0'||in>'9')) in=getchar();if(in=='-'){ IsN=true;num=0;}else num=in-'0';while(in=getchar(),in>='0'&&in<='9'){num*=10,num+=in-'0';}if(IsN) num=-num;return true;}
ll n,m,k,q;
ll a[maxx];
ll sum[maxx];
ll b[maxx];
int main()
{
    ll t;
    // 4 m 11
    ll s;
    cin>>n>>k>>s;
    sum[0]=0;
    a[0]=0;
    rep(i,1,k)
    {
        a[i]=i;
        sum[i]=sum[i-1]+i;
    }
    ll nn=max(n,k);
    rep(i,k+1,2*nn+100)
    {
        sum[i]=i%(k+1);
        a[i]=i%(k+1);
        sum[i]+=sum[i-1];
    }
    //rep(i,1,2*n) cout<<a[i];
    // 长度为n的最小值

    rep(i,0,k)
    {
        ll num;
        if(i==0) num=sum[n-1];
        else num=sum[i+n-1]-sum[i-1];
       // cout<<num<<endl;
        ll p=s-num;
       // printf("dqw\n");
        if(p>=0&&p%(k+1)==0 )
        {
            //cout<<p<<endl;
            // keyi
            ll geshu=p/(k+1) ;
            ll zhi=geshu/n;
            rep(j,i,i+n-1) a[j]+=zhi*(k+1);
            geshu=geshu%n;
            // cout<<geshu<<endl;
            //rep(j,i,i+n-1) printf("%lld ",a[j]);
            while(1)
            {
                if(geshu==0) break;
                rep(j,i,i+n-1)
                {
                    if(j==i)
                    {
                        if(a[j]+k+1-a[j+1]==k || a[j]+k+1==a[j+1]-1 )
                        {
                           // printf("dwqwdq\n");
                            a[j]+=k+1;
                            geshu--;
                        }
                    }
                    else if(j==i+n-1)
                    {
                        if(a[j]+k+1==a[j-1]-k|| a[j]+k+1==a[j-1]+1 )
                        {
                            a[j]+=k+1;
                            geshu--;
                        }
                    }
                    else
                    {
                        ll x=a[j]+k+1;
                        if( (x==a[j-1]+1||x==a[j-1]-k)&&(x==a[j+1]-1||x==a[j+1]+k) )
                        {
                            a[j]+=k+1;
                            //printf("dwqwdq\n");
                            geshu--;
                        }

                    }
                    if(geshu==0) break;
                }
                if(geshu==0) break;
            }
            rep(j,i,i+n-1) printf("%lld ",a[j]);
            printf("\n");
            return 0;
        }
    }
    
    printf("-1\n");
    return 0;
}
/***


***/



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值