大一上训练赛1 cf div4 round640

心得:O(n^2)的大概率超时 少用;

        学会快读;

        前缀和;

        观察样例,再读题,再找平凡/特殊值找规律;

        EF一般为构造题目 本次的规律比较好找;

     

      

B题个人思路

nk奇偶性分别讨论即可 -1或者-2

C题:看了zz同学的代码 大有启发;

下面是我的思路:

每n个数,就有n-1个不能被n整除的数;

由此1到k中 有k/n*(n-1)个不能被n整除的;

我们需要1到几呢?我们需要至少要取1到k/(n-1)*n(注意这个数会被n整除),才能有k/(n-1)*(n-1)个不能被n整除的;

所以剩下的需要的数有k mod n-1个,若k mod n-1=0 那么我们的答案就是k/(n-1)*n-1;

若不为0那么我们的答案是k/(n-1)*n+k mod n-1;

然后后面是官方题解的思路:

第四题为一个模拟题 结果卡了我好久呜呜呜 太菜了  考完几分钟就改好了 休息挺重要的 到后面头脑不清醒 反思!

#include<bits/stdc++.h>
using namespace std;
int _,n,k,moves=0,a=0,b=0;
int x[1006]={0};
void main2()
{
   moves=0,a=0,b=0;
   cin>>n;
   int cnt1=n-1,cnt2=1,len_residue=n-1;
   for(int i=0;i<n;i++) cin>>x[i];
   int size=x[0];
   a+=size;
   moves++;
   while(n!=1)
   {
   	    int sum=0;
   	    for(int i=cnt1;i>=0;i--)
   	    {
   	        sum+=x[i];
   	        len_residue--;
   	        if(len_residue==0)
			{
				moves++;
				b+=sum;
				break;
			}
		    else if(sum>size)
		    {
			    b+=sum;
		    	size=sum;
		    	moves++;
		    	cnt1=i-1;
		    	break;
			}
		}
		if(len_residue==0)
		break;
		sum=0;
		for(int i=cnt2;i<n;i++)
		{
   	        sum+=x[i];
   	        len_residue--;
   	        if(len_residue==0)
			{
				moves++;
				a+=sum;
				break;
			}
		    else if(sum>size)
		    {
			    a+=sum;
		    	size=sum;
		    	moves++;
		    	cnt2=i+1;
		    	break;
			}
		}
		if(len_residue==0)
		break;
   }
   cout<<moves<<" "<<a<<" "<<b;
}

int main()
{
	ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
	cin>>_;
	while(_--){
		main2();
		if(_) cout<<endl;
	}
	return 0;
}

第五题

这题用到前缀和+暴力枚举+桶数组原理,前段时间一直接触差分,倒把前缀和给整忘了,,,汗

#include <bits/stdc++.h>
using namespace std;
const int N = 8008;

int a[N], sum[N], m[N];

int main(){
    int t; cin >> t;
    while(t --){
        memset(m, 0, sizeof m); 
        int n; cin >> n;
        sum[0] = 0;
        for(int i = 1; i <= n; i ++){
            scanf("%d", &a[i]);
            m[a[i]] ++; // 记录每个数出现的次数
            sum[i] = sum[i - 1] + a[i]; // 前缀和
        }
        int ans = 0;
        for(int l = 1; l <= n; l ++)
            for(int r = l + 1; r <= n; r ++){
                int t = sum[r] - sum[l - 1];
                if(t > n) continue; // 每个数都是 <= n,> n 显然不合法
                ans += m[t];
                m[t] = 0; // 加了必须清空
            }
        cout << ans << endl;
    }
    return 0;
}

第六题暴力构造:比赛的时候没来得及看,我现在想想,下面是我自己的思路;

n0+n1+n2+1就是这个串的元素总数,n1如果为0,那么全零或者全一,然后就是n0+1个0或者n2+1个1;

n1≠0的话,我是先想到串的元素值之和,我们对ni*i进行求和,发现这个和就是串首尾元素*1+其他元素*2,故可以从奇偶性去讨论;

如果这个和是奇数,那么首尾一个1一个0;如果是偶数,则首尾2个1或者2个0;(这个和与n1有关)

然后我考虑了连续的一和零的规律,样例1,n2=5,那么至少6个1,然后每多一个1说明,连续的1被分成的两段,n0=1,至少两个0,每多一个0说明连续的0被分成了两段。

那么对于n1为奇,则1的个数是(n1+1+2*n2)/2,0的个数是n1+n0+1-(n1+1)/2。

连续0的个数是,连续1的个数是;

n1为偶,,,整体感觉太过复杂,不够简洁,说明方向有问题;

然后我看了官方题解;

如果在1和0之间插入0,那么n1个数不变,同理,在0和1直接插入1;

所以思路是1和0输出n1+1个,然后第一个0前面插入n0个0,第一个1前面插入n2个1即可;

然后有个insert函数(?;

第七题构造:

n<4时不成立,

n=4时,3 1 4 2

n>4,考虑差分属于2-4,故考虑奇数和偶数分开来,比如7,我这样,1,3,5,7,2,4,6

不大行,然后变成1,3,5,7,6,4,2,接近了,然后将4和6互换即可。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值