2022CCPC桂林站(A M C E)(模拟、逆序对、规律、exgcd)

Problem - A - Codeforces

A. Lily

思路:简单的签到,所有不在 L 旁的字符替换为 C 即可。

代码:(以及注意注释里的部分) 是谁签到题都WA呀 哦是我呀.jpg 

#include<bits/stdc++.h>
using namespace std;
int main(){
    int n;cin>>n;
    string s;cin>>s;
    for(int i=0;i<n;i++)if(s[i]=='.')s[i]='C';
    for(int i=0;i<n;i++){
        if(s[i]=='L'){//注意这里L的判断
            if(i!=0&&s[i-1]=='C')s[i-1]='.';//注意这里C的判断
            if(i!=n-1&&s[i+1]=='C')s[i+1]='.';
        }
    }
    cout<<s;
    return 0;
}

Problem - M - Codeforces

M. Youth Finale

提交的结果(题目限制3s)

2230 ms 11900 KB

思路:

冒泡排序求要交换的次数=求逆序对个数

所以可以用归并排序或树状数组求逆序对O(nlogn)

之后输入m个操作,求执行该操作后的逆序对个数

为了记录每一次的操作后数组的状态,用了stl的list来记录

对于reverse操作,新逆序对个数=组合数nC2-旧逆序对个数

对于swap操作,设交换了y,新逆序对个数=(n-y)-(y-1)=n-2y+1

务必记得开long long

#include<bits/stdc++.h>
#define int long long
using namespace std;
int a[300005],base[300005];
int ans=0,l,r;
void mergesort(int l,int r)//归并排序
{
    if(l==r) return;
    int mid=(l+r)>>1;
    if(l<=mid) mergesort(l,mid);  //左递归
    if(mid+1<=r) mergesort(mid+1,r);//右递归
    int ln=l,rn=mid+1,k=l;  //合并操作
    while(ln<=mid&&rn<=r){
        if(base[ln]<base[rn]) a[k++]=base[ln++];
        else{
            a[k++]=base[rn++];
            ans+=mid-ln+1;
        }
    }
    while(ln<=mid) a[k++]=base[ln++];
    while(rn<=r) a[k++]=base[rn++];
    for(int i=l;i<=r;i++){
        base[i]=a[i];
    }
}
signed main()           //务必记得开long long
{
    list<int> li;       //因为给了3秒 最终耗时2230 ms
    int n,m;cin>>n>>m;
    int zu=n*(n-1)/2;
    for(int i=1;i<=n;i++){cin>>base[i];li.push_back(base[i]);}
    mergesort(1,n);//交换次数就是在求逆序对
    cout<<ans<<'\n';char x;
    for(int i=0;i<m;i++){
        cin>>x;
        if(x=='R'){reverse(li.begin(),li.end());ans=zu-ans;cout<<ans%10;}
        else{
            int y=*li.begin();
            li.erase(li.begin());
            li.push_back(y);
            ans+=(n-y);
            ans-=(y-1);
            cout<<ans%10;
        }
    }
}

Problem - C - Codeforces

C. Array Concatenation

思路:

 

代码:

#include<bits/stdc++.h>
using namespace std;
#define int long long
int a[100005];
int b[200005];//注意这里要开两倍,不然WA
const int mod=1000000007;
long long binpow(long long a, long long b, long long m) {
  a %= m;
  long long res = 1;
  while (b > 0) {
    if (b & 1) res =res * a % m;
    a =a * a % m;
    b >>= 1;
  }
  return res;
}
signed main()
{
    int n,m;cin>>n>>m;
    for(int i=1;i<=n;i++){cin>>a[i];}
    for(int i=1;i<=n;i++){b[i]=a[n-i+1];b[n+i]=a[i];}
    int s=0,ss=0;
    for(int i=1;i<=2*n;i++){
        s=s+b[i];s=s%mod;
        ss=ss+s;ss=ss%mod;
    }
    int ans1=(ss*binpow(2,m-1,mod)%mod+binpow(2,m-1,mod)*(binpow(2,m-1,mod)+mod-1)%mod*2*n%mod*s%mod*binpow(2,mod-2,mod)%mod)%mod;
    s=0,ss=0;
    for(int i=1;i<=n;i++){
        s=s+a[i];s=s%mod;
        ss=ss+s;ss=ss%mod;
    }
    int ans2=(ss*binpow(2,m,mod)%mod+binpow(2,m,mod)*(binpow(2,m,mod)+mod-1)%mod*n%mod*s%mod*binpow(2,mod-2,mod)%mod)%mod;
    cout<<max(ans2,ans1)<<endl;

    return 0;
}

E. Draw a triangle

Problem - E - Codeforces

思路(官方题解):

 

注意:

1.向量不要写反,A(x1,y1)B(x2,y2)AB(x2-x1,y2-y1)

2.叉积不要写反,注意exgcd为 exgcd(-b,a,x,y);

3.遇到x1=x2 or y1=y2 要注意判断

#include<bits/stdc++.h>
using namespace std;
#define int long long
inline int exgcd(int a, int b, int &x, int &y)
{
	if(! b){x=1;y = 0;}
	else{
		exgcd(b, a % b, x, y);
		int t=x;
		x=y;y=t-(a/b)*y;
	}
	return 0;
}
signed main()
{
    int T;cin>>T;
    while(T--){
        int x1,x2,y1,y2;
        cin>>x1>>y1>>x2>>y2;
        int a=(-x1+x2),b=(-y1+y2);
        if(a==0){
            cout<<x1+1<<" "<<y1<<'\n';
        }
        else if(b==0){
            cout<<x1<<" "<<y1+1<<'\n';
        }
        else{
        int x,y;
        exgcd(-b,a,x,y);
        cout<<x1+x<<" "<<y1+y<<'\n';
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/zy98zy998/article/details/127635673