Codeforces Round #740 (Div. 2, based on VK Cup 2021 - Final (Engine))ABCD1D2E题解


A - Simply Strange Sort

题目链接
题意: a [ i ] > a [ i + 1 ] a[i]>a[i+1] a[i]>a[i+1]就可以交换直到序列升序,第奇数次迭代 i i i 只能是奇数,偶数同理

暴力摸你
一开始没看题直接乱摸T^T
然后就是要注意check整个序列 奇数没有能交换的不一定代表序列有序可能在偶数

int main(){
    int t;cin>>t;
    while(t--){
        int n;cin>>n;
        for(int i=1; i<=n; i++) cin>>a[i];
        int cnt=0;
        while(1) {
            int q=0;
            for(int i=1; i<n; i++) {
                if(cnt%2==0&&i%2==1&&a[i]>a[i+1]) {
                    swap(a[i], a[i+1]);
                    i++;
                    q++;
                }
                if(cnt%2==1&&i%2==0&&a[i]>a[i+1]) {
                    swap(a[i], a[i+1]);
                    i++;
                    q++;
                }
            }
            for(int i=1; i<=n; i++) {
                if(a[i]!=i) q++;
            }
            if(q) cnt++;
            else break;
        }
        cout<<cnt<<endl;
    }
    return 0;
}

B - Charmed by the Game

题目链接
题意 A l i c e Alice Alice B o b Bob Bob轮流发球 问会有几次我发球但是我输满足 A l i c e Alice Alice赢了 a a a B o b Bob Bob 赢了 b b b

就摸你几组样例
a = = 0 ∣ ∣ b = = 0 a==0||b==0 a==0b==0
a = = b a==b a==b
a + b a+b a+b 是奇数和偶数的情况

int main(){
    int t;cin>>t;
    while(t--){
        int a, b;cin>>a>>b;
        if(a==0||b==0) {
            if((a+b)%2==0) cout<<1<<endl<<(a+b)/2<<endl;//偶数
            else cout<<2<<endl<<(a+b)/2<<" "<<(a+b)/2+1<<endl;//奇数
        }else {
            if(a==b) {
                cout<<a+1<<endl;
                for(int i=0; i<=a+b; i+=2) {
                    cout<<i<<" ";
                }
                cout<<endl;
            }else {
                if(a>b) swap(a, b);
                if((a+b)%2==1) {
                    int cnt=0;//最小是(b-a)/2
                    for(int i=(b-a)/2; i<=a+b-(b-a)/2; i++) cnt++;
                    cout<<cnt<<endl;
                    for(int i=(b-a)/2; i<=a+b-(b-a)/2; i++) cout<<i<<" ";
                    cout<<endl;
                }else {
                    cout<<a+1<<endl;//个数是最小的+1 因为最多能改这么多下次
                    for(int i=(b-a)/2; i<=a+b-(b-a)/2; i+=2) {
                        cout<<i<<" ";
                    }
                }
            }
        }
    }
    return 0;
}

C - Deep Down Below

题目链接
题意:有 n n n 个洞穴,洞穴里有 x x x 个怪物,选择洞穴的顺序可以变,进入该洞穴的顺序不能变就是只能按顺序打怪兽,只有当前武力值大于怪物的值才能打败他,打败之后武力值 + 1 +1 +1 ,问最小武力值使进入所有洞穴打败所有怪兽

直接贪心摸你

struct node {
    int maxx;
    vector<int> g;
}a[maxn];
bool cmp(node a, node b) {
    return a.maxx<b.maxx;
}
signed main(){
    int t;cin>>t;
    while(t--) {
        int n;cin>>n;
        for(int i=1; i<=n; i++) {
            a[i].maxx=0;
            a[i].g.clear();
            int x; cin>>x;
            for(int j=1; j<=x; j++) {
                int w; cin>>w;
                a[i].g.push_back(w);
                if(a[i].maxx<w-j+1) {
                    a[i].maxx=w-j+1;//要的是相对的位置 因为之前打败的可以+1
                }
            }
        }
        sort(a+1, a+1+n, cmp);//按照maxx排序
        int cnt=0;
        int lil=a[1].maxx;
        for(int i=1; i<=n; i++) {
            for(int j=0; j<a[i].g.size(); j++) {
                if(lil+cnt<=a[i].g[j]) {//不够就把力量变大
                    lil=a[i].g[j]-cnt+1;
                }
                cnt++;//记录之前打败的+1的次数
            }
        }
        cout<<lil<<endl;
    }
    return 0;
}

D1 - Up the Strip (simplified version)

题目链接
题意:你有一条垂直带有 n n n 个单元格你把一块令牌从 n n n 移到 1 1 1 ,当令牌在单元格 x > 1 x>1 x>1 可以有下面两种类型移动
1 1 1减法:选择在 1   x − 1 1~x-1 1 x1 移动令牌从 x x x x − y x-y xy
2 2 2基数除法:选择在 z z z 2   x 2~x 2 x 移动令牌从 x x x x / z x/z x/z(向下取整
问有几种方案数量
给你 n 和 m o d n和mod nmod

(减法) d p 1 [ i ] = s u m [ i − 1 ] , 其 中 s u m [ i ] = d p 1 [ 1 ] + . . . . . . + d p 1 [ i ] dp1[i]=sum[i-1],其中sum[i]=dp1[1]+......+dp1[i] dp1[i]=sum[i1]sum[i]=dp1[1]+......+dp1[i]但是可以直接树状数组求出
(整除) dp2[i]=dp2[i/2]+…+dp2[i/i]
我们发现对于一个固定的 j j j i / j i/j i/j 具有周期性,并在 ( i / j ) (i/j) (i/j) + 1 +1 +1,则转移方程可写为:
d p [ i ] = s u m [ i ] + ( . . . . d p [ i / j ] − d p [ ( i / j ) − 1 ] ) dp[i]=sum[i]+(....dp[i/j]-dp[(i/j)-1]) dp[i]=sum[i]+(....dp[i/j]dp[(i/j)1])(其中i%j==0且j>=2)
时间复杂度O(Nsqrt(N))

int dp[N];//#define int long long
int n, M;
int c[N];
int lowbit(int x) {
    return x&(-x);
}
void updata(int i,int k) {
    while(i <= n) {
        c[i] += k;
        i += lowbit(i);
    }
}
int getsum(int i) {
    int res = 0;
    while(i > 0) {
        res += c[i];
        i -= lowbit(i);
    }
    return res;
}
signed main() {
	 ios::sync_with_stdio(false);cin.tie(0);
     cin>>n>>M;
	 dp[1]=1;
	 int sum=1;
	 updata(1, 1);
	 for(int i=2; i<=n; i++){
	 	 int a=0, k=1, b=0;
	 	 for(int j=1; j*j<=i;j++){
	 	     a=(a+dp[j]*(i-i/(j+1)-b)%M)%M;
			 b=((i-i/(j+1)+M)%M)%M;
			 if(j!=i/j){
			 	 if(i==1) continue;
			 	 a=(a+dp[i/j])%M;
			 }
		 }
		 sum=a%M+getsum(i-1)%M;
		 sum%=M;
		 updata(i, sum);
		 dp[i]=sum;
	 }
	 cout<<dp[n]<<'\n';
	 return 0;
}

总结

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值