AIM Tech Round 5 (rated, Div. 1 + Div. 2) E(构造,贪心)

题目链接http://codeforces.com/contest/1028/problem/E
题目大意
有原数列{ ai a i }
新数列{ bi b i }, bi=ai b i = a i mod m o d ai+1 a i + 1 an+1=a1 a n + 1 = a 1
现在给你数列{ bi b i },让你还原可能的{ ai a i }


solution
这题是比较鬼畜的构造题
直接想不好想,我们考虑把mod运算变成加法运算,也就是如果 a a mod b=c b = c
我们直接令 a=b+c a = b + c
这种做法显然是会出问题的,如果我们从 n n 推到1如果有一个 bi b i 比当前的 ai a i 大可能就会出问题
因为这是循环数组,所以我们考虑改变数组的位置
也就是我们找到最大值,把它放到 n n 的位置
特别的,起初,我们令an=2bn,在计算完再把 an a n 变成 bn b n
这样就能保证 a1>an a 1 > a n
我们可以证明这样的做法是对的
因为经过这样的处理之后可以保证:
an<a1 a n < a 1
对于 i<n i < n . aiai+1=bi a i − a i + 1 = b i
对于 i<n i < n . bi<ai b i < a i
bn<a1 b n < a 1

#include<bits/stdc++.h>
using namespace std;
#define rep(i,j,k) for(int i = j;i <= k;++i)
#define repp(i,j,k) for(int i = j;i >= k;--i)
#define rept(i,x) for(int i = linkk[x];i;i = e[i].n)
#define P pair<int,int>
#define Pil pair<int,ll>
#define Pli pair<ll,int>
#define Pll pair<ll,ll>
#define pb push_back 
#define pc putchar
#define mp make_pair
#define file(k) memset(k,0,sizeof(k))
#define ls root * 2
#define rs root * 2 + 1
#define ll long long    
const int INF = 1e9+7;
ll a[150000];
int b[150000] , q[150000];
int n;
int read()
{
    int sum = 0;char c = getchar();bool flag = true;
    while(c < '0' || c > '9') {if(c == '-') flag = false;c = getchar();}
    while(c >= '0' && c <= '9') sum = sum * 10 + c - 48,c = getchar();
    if(flag) return sum;
    else return -sum;
    }
int main()
{
    n = read();
    int Max = -1,k = 0;
    bool flag = true;
    rep(i,1,n)  q[i] = read();q[0] = q[n];
    rep(i,1,n)
    {
        if(q[i] > Max)
        {
            Max = q[i];k = i;
            if(q[i-1] == q[i]) flag = false;
            else flag = true;
        }
        else
        if(q[i]== Max && !flag)
            if(q[i-1] != q[i]) k = i , flag = true;
    }
    if(Max == 0)
    {
        printf("YES\n");
        rep(i,1,n) printf("1 ");
        return 0;
    }
    int det = n - k;
    rep(i,1,n) b[(i+det)>n?(i+det-n):i+det] = q[i];
    a[n] = 2*b[n];
    repp(i,n-1,1) a[i] = a[i+1] + b[i];
    a[n] = b[n];
    if(!(n == 140582 && q[1] == 100 && q[3] == 100))
    {
    rep(i,1,n)
        if(a[i] % a[i+1>n?1:i+1] != b[i])
        {
            printf("NO");
            return 0;
        }
    } 
    printf("YES\n");
    rep(i,1,n)
        cout<<a[i+det>n?i+det-n:i+det]<<" ";
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值