Codeforces Round #636 (Div. 3) ABCD

A   等比数列求和,找一个n可以整除的就行

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    ll ans[35];
    int main(){
    	ll n;
    	int i,j;
    	ans[0]=1;
    	for(i=1;i<35;i++){
    		ans[i]=ans[i-1]*2;
    //		cout<<"i  "<<ans[i]<<endl;
    	}
    	int t;
    	cin>>t;
    	
    	for(i=0;i<t;i++){
    		int flag=1;
    		cin>>n;
    		for(j=2;j<35&&flag;j++){
    //			cout<<"n  ans  "<<n<<" "<<ans[j]<<endl;
    			if(n%(ans[j]-1)==0){
    				cout<<n/(ans[j]-1)<<endl;
    				flag=0;
    			}
    		}
    	}
     
     
    }

B   构造题,因为不管多少个偶数相加都为偶数,但是奇数个奇数相加等于奇数,所以和必定是偶数

所以如果\frac{n}{2}  为奇数,就无法构造出这样的数列

当偶数的排列固定为  2 4 6 8 ……     而 奇数的排列固定为 1 3 5 7……   只要通过和计算出最后一个奇数就行       因为前面每一个偶数都比奇数大   例如 2>1 \qquad 4>3 \qquad 6>5    所以最后一个奇数一定远大于偶数的最后一项,  所以不用担心  最后一个奇数会和前面的奇数相等,   

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    int main(){
    	std::ios::sync_with_stdio(false);
    	int t,n,i;
    	cin>>t;
    	while(t--){
    		cin>>n;
    		if(n%4==0){
    			cout<<"YES"<<endl;
    			int cnt=n/2;
    			cout<<"2";
    			for(i=2;i<=cnt;i++){
    				cout<<" "<<2*i;
    			}
    			for(i=1;i<cnt;i++){
    				cout<<" "<<2*i-1;
    			}
    			cout<<" "<<3*cnt-1<<endl;
    		}
    		else{
    			cout<<"NO"<<endl;
    		}
    	}
     
     
     
    }

C   没完全看懂题目意思    看了别人题解  

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    const ll INF=0x3f3f3f3f3f3f3f3f ;
    ll a[200005];
    int main(){
    	std::ios::sync_with_stdio(false);
    	int t,n,i;
    	ll maxn,ans=0;
    	cin>>t;
    	while(t--){
    		ans=0;
    		cin>>n;
    		for(i=0;i<n;i++){
    			cin>>a[i];
    		}
    		maxn=a[0];
    		for(i=1;i<n;i++){
    			if(a[i]*maxn>0){
    				maxn=max(maxn,a[i]);
    			}
    			else{
    				ans+=maxn;
    				maxn=a[i];
    			}
    		}
    		cout<<ans+maxn<<endl;
    	}
     
     
     
    }

D   因为和是一定的     2 \leq sum \leq 2 \times k

可以吧每一个和需要的更改次数求出来

那么对于每一对数      a[i] \qquad a[n-i+1]     

每个范围对应的修改次数如下

2\leq sum < min(a[i],a[n-i+1])+1 \qquad 2 \\ min(a[i],a[n-i+1])+1\leq sum \leq max(a[i],a[n-i+1])+k \qquad 1 \\ max(a[i],a[n-i+1])+k< sum \leq 2 \tims k \qquad 2

这里有个特殊点就是   sum = a[i]+a[n-i+1]   这个点,需要修改0次

 

每一个范围的节点都可以求出来的    需要更改元素的次数也都知道了  然后用差分法

最后求和最小值

然后就是因为数据给的范围都是t组数据之和   所以范围不要开太大了    memset也不要用  会TLE

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    const int INF=0x3f3f3f3f;
    struct node{
    	int val,time;
    };
    node review[100005];
    int a[200005];
    map<int,int>index;
    int dp[400005];
    bool cmp(node a,node b){
    	return a.time<b.time;
    }
     
    int main(){
    	 std::ios::sync_with_stdio(false);
    	int t,n,k,i;
    	cin>>t;
    	
    	while(t--){
    		cin>>n>>k;
    		int maxn=-INF;
    		for(i=1;i<=n;i++){
    			cin>>a[i];
    			maxn=max(maxn,a[i]);
    		}
    		for(i=0;i<=2*maxn+5;i++){
    			dp[i]=0;
    		}
    		for(i=1;i<=n/2;i++){
    			int left=min(a[i],a[n-i+1])+1;
    			int right=max(a[i],a[n-i+1])+k;
    			dp[0]+=2;
    			dp[left]-=1;
    			dp[a[i]+a[n-i+1]]-=1;
    			dp[a[i]+a[n-i+1]+1]+=1;
    			dp[right+1]+=1;
    		}
    		int ans=INF;
    		for(i=1;i<=2*maxn;i++){   //差分
    			dp[i]+=dp[i-1];
    //			cout<<i<<"  I  "<<dp[i]<<endl;
    			ans=min(ans,dp[i]);
    		}
    		cout<<ans<<endl;
    	} 
     
     
     
    }

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值