• CF#587Div3


    #587Div3

    A

    题意

    • 给定一个字符串只含 (a,b)
    • 使得每个前缀的 (a)(b) 的个数相同(当然是偶数位上的

    解法

    • 一路改,哪个多就变成另一种

    100分代码

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    char x,good[200005];
    int n,one,two,ans;
    int main()
    {
    	scanf("%d",&n);
    	for(int i=1;i<=n;i++){
    		cin>>x;
    		if(x=='a') one++;
    		else two++;
    		if(i%2) {
    			good[i]=x;
    			continue;
    		}
    		if(one==two){
    			good[i]=x;
    			continue;
    		}
    		ans++;
    		if(one>two) good[i]='b',two++,one--;
    		else good[i]='a',one++,two--;
    	}
    	printf("%d
    ",ans);
    //	cout<<c<<endl;
    	for(int i=1;i<=n;i++) cout<<good[i];
    	return 0; 
    }
    

    B

    题意

    • 排序

    解法

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    int n,ans;
    struct node{
    	int id,x;
    }d[1005];
    bool cmp(node a,node b){
    	return a.x >b.x ;
    }
    int main(){
    	scanf("%d",&n);
    	for(int i=1;i<=n;i++) scanf("%d",&d[i].x),d[i].id =i;
    	sort(d+1,d+n+1,cmp);
    	for(int i=1;i<=n;i++)
    		ans+=d[i].x*(i-1)+1;
    	printf("%d
    ",ans);
    	for(int i=1;i<=n;i++) printf("%d ",d[i].id );
    	return 0;
    }
    

    D

    题意

    • (n) 个数,有 (y) 个数是被减掉了若干个(z)后的,最初都是 (x)
    • 求最小的 (y)(z)

    解法

    • 从小到大排序,我们按照最大数当 (x) ,求出其他数和最大值的差,求这些差值的最大公约数。就是最少的人数。差值的和是剪掉多少个 (z)

    代码

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #define ll long long 
    using namespace std;
    int n;
    ll ans,gd;
    ll a[200005];
    ll gcd(ll a,ll b){
    	if(b==0) return a;
    	return gcd(b,a%b);
    }
    int main()
    {
    	scanf("%d",&n);
    	for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
    	sort(a+1,a+n+1);
    	for(int i=1;i<n;i++){
    		a[i]=a[n]-a[i];
    		ans+=a[i];
    		gd=gcd(gd,a[i]);
    	}
    	printf("%lld %lld",ans/gd,gd);
    	return 0;
    }
    

    E1

    题意

    类似这样的数列 1 2 3 4 5 6 7 8 9 1 0 1 1 1 2 1 3 1 4 1 5 1 6......
    求第 (n)
    (n<10^9)

    解法

    按个数分组,第一组是1 第二组是 1 2 第三组是 1 2 3 第n组是 1 2 3 4 5 ...n
    暴力找到在哪个组
    再预处理出1-n个数的第几项是0-9中的哪个数
    暴力在这个组内,找到答案

    100分代码

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<cmath> 
    using namespace std;
    int Q,res,cnt,maxx;
    int num[500005],p[500005],now[500005];
    struct node{
    	int id,k,ans;
    }q[505];
    bool cmp(node a,node b){
    	return a.k <b.k ;
    }
    bool cmp2(node a,node b){
    	return a.id <b.id ;
    }
    int main()
    {
    	scanf("%d",&Q);
    	for(int i=1;i<=Q;i++){
    		scanf("%d",&q[i].k);
    		q[i].id =i;
    		maxx=max(maxx,q[i].k);
    	}
    	sort(q+1,q+Q+1,cmp);
    	maxx=sqrt(2*maxx)+1;
    	for(int i=1;i<=maxx;i++){
    		int x=i,cnt=0;
    		while(x){
    			now[++cnt]=x%10;
    			x/=10;
    		}
    		num[i]=num[i-1]+cnt;
    		while(cnt){
    			++res;
    			p[res]=now[cnt];
    			--cnt;
    	    }
    	}
        int from=1,last=0;
    	for(int i=1;i<=Q;i++){
    		while(from<=maxx){
    			if(num[from]+last<q[i].k){
    				last+=num[from++];
    				continue;
    			}
    			
    			q[i].k -=last;
    			q[i].ans =p[q[i].k];
    			break;
    		}
    	}
    	sort(q+1,q+Q+1,cmp2);
    	for(int i=1;i<=Q;i++) printf("%d ",q[i].ans );
    	return 0;
    }
    

    E2

    n<10^18

    • 首先二分在哪个组,然后二分在这个组的哪个位置
    • 考虑
    • 1
    • 1 2
    • 1 2 3
    • 1 2 3 4
    • 1 2 3 4 5
    • 1 2 3 4 5 ....9
    • 1 2 3 4 5 6 ... 10
    • 设位数是 (n)
    • 上面这个三角形前x行的位数和,可以通过把位数分类,位数相同的在一类。
    • 这样就可以如下图一样求
    • enter image description here

    enter image description here

    每一个三角形的数位和是 (j*(9*i)*(9*i+1)/2) ,每个三角形下的矩形面积是 (j*9*i*(x-10*i+1))
    (j) 是指这一类数的位数, (i=10^{j-1})
    三角形算和相当于是一个等差数列求和

    • 注意边界,因为10是算在第二组的

    • 然后二分出组后,再二分在组中的位置

    • 看下面找规律

    1 2 3 4 5 6 7 8 9
    (1*9*10^0=1*(9-1+1))

    10 11 12 13 14 15 16 .... 99
    (2*9*10^1=2*(99-10+1))

    100 101 102 103 104 105 106 107 .....999
    (3*9*10^3=3*(999-100+1))

    (10^x) (10^x+1) (10^x+2) (10^x+3) (...10^{x+1}-1)
    ((x+1)*9*10^{x+1}=(x+1)*(10^{x+1}-1-10^x+1))

    • (i=10^{x},j=x+1)
    • 每种数位相同的数有 (9*i*10*j) 个,遇到不是10的整数倍的,就 ((n-i+1)*j)

    100分代码

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #define ll long long 
    using namespace std;
    ll n,x;
    int T;
    ll check1(ll x){
    	ll now=0;
    	for(ll i=1,j=1;i<=x;i*=10,j++){
    		if(10*i<=x) now+=(9*i*(x-i*10+1)*j)+j*(9*i*(1+9*i))/2;
    		else now+=j*(x-i+1)*(x-i+2)/2;
    		if(now>1e18) return 1e18;
    	}
    	return now;
    }
    ll check2(ll x){
    	ll now=0;
    	for(ll i=1,j=1;i<=x;i*=10,j++){
    		if(i*10<=x) now+=9*i*j;
    		else now+=(x-i+1)*j;
    		if(now>1e18) return 1e18;
    	}
    	return now;
    }
    int main()
    {
    	scanf("%d",&T);
    	while(T--){
    		scanf("%lld",&x);
    		ll l=0,r=1e9,mid;
    		while(l<=r){//二分组数 
    			mid=(l+r)>>1;
    			if(check1(mid)<x) l=mid+1;
    			else r=mid-1;
    		}
    		x-=check1(r);
    		r=l;
    		l=1;
    		while(l<=r){//二分组中的第几个数 
    			mid=(l+r)>>1;
    			if(check2(mid)<x) l=mid+1;
    			else r=mid-1;
    		}
    		x-=check2(r);
    		ll res=l,cnt=0;
    		while(res){
    			++cnt;
    			res/=10;
    		}
    		x=cnt-x;
    		for(ll i=1;i<=x;i++) l/=10;
    		printf("%lld
    ",l%10); 
    	}
    	return 0;
    }
    
  • 相关阅读:
    双端队列
    顺序循环队列
    顺序队列
    Counting Triangles(hd1396)
    蒟蒻之栈模拟递归
    链栈以及顺序栈应用—算数表达式
    栈的简单应用-进制转换
    链栈
    共享栈
    顺序栈
  • 原文地址:https://www.cnblogs.com/Vimin/p/11600788.html
Copyright © 2020-2023  润新知