week2

蓝桥杯模拟赛 2

思路:当下几个字符组成数字n,输出n个当前字符,否则直接输出
string a,ans;
    cin>>a;
    for(int i=0;i<a.size();++i){
        if(i<a.size()-1&&a[i]>=65&&a[i+1]<65){
            int k=i+2;
            ll t=a[i+1]-'0';
            while(a[k]<65&&k<a.size()){
                t=t*10+(a[k]-'0');
                k++;
            }
            for(ll j=0;j<t;++j)ans+=a[i];
            i=k-1;
        }
        else{
            ans+=a[i];
        }
    }
    cout<<ans;

 

 
思路:输入时判断最大最小和统计总分
int n,a[N],ma=-1,mi=101;
    ll s=0;
    cin>>n;
    for(int i=0;i<n;++i){
        cin>>a[i];
        if(a[i]>ma)ma=a[i];
        if(a[i]<mi)mi=a[i];
        s+=a[i];
    }
    cout<<ma<<'\n'<<mi<<'\n';
    cout<<fixed<<setprecision(2)<<double(s)/double(n);

 

 
思路:除到小于0就停止
ll n;
    cin>>n;
    cout<<n<<' ';
    for(ll i=n;i>0;){
        i>>=1;
        if(i>0)cout<<i<<' ';
    }

 

 
思路:注意前导0和后缀0
string a[12]={"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"};
    string b,x,y;
    cin>>b;
    x=b.substr(0,3);
    y=b.substr(3,2);
    for(int i=0;i<12;++i)
        if(x==a[i]){
            cout<<i+1<<' ';break;
        }
    if(y[0]!='0')cout<<y[0];
    cout<<y[1];

 

 
思路:判断年的反转是否为合法的月日,是否满足ababbaba
bool check_vaild(int n)
{
    int year = n / 10000 , month = n % 10000 / 100 , day = n % 100;
    if(month < 0 || month > 12)   return false;
    if(day < 0 || (day > days[month] && month != 2))    return false;
    int x = 0;
    if(month == 2)
        x = year % 4 == 0 && year % 100 || year % 400 == 0;
    if(day > days[month] + x)   return false;
    return true;
}
 
bool check_ABAB(int n)
{
    int a = n / 10000000 , b = n / 1000000 % 10 , c = n /100000 % 10 , d = n / 10000 % 10;
    if(a == c && b == d && a != b)  return true;
    return false;
}

int main()
{
    int n;
    cin>>n;

    int falg = 1;
    for(int i = n / 10000;i < 10000;i ++)
    {
        int x = i , t = i;
        for(int j = 0;j < 4;j ++)
            x = x*10 + t%10 , t /= 10;
        if(check_vaild(x) && x > n && falg)
        {
            printf("%d\n",x);
            falg = 0;
        }
        if(check_vaild(x) && check_ABAB(x) && x > n)
        {
            cout<<x;
            break;
        }
    }


    return 0;
}

 

 
思路:每加一条不重合直线,s都会加一,若该线与已存的直线有一个交点则s++,且每个交点需不同,用set存即可
int main(){
    cin.tie(0),cout.tie(0);
    int n,s=1;
    double a,b;
    set<pair<double,double>>l;
    cin>>n;
    for(int i=0;i<n;++i){
        cin>>a>>b;
        if(l.count({a,b})==1)continue;
        if(l.size()>0) {
            set<pair<double,double> >p;
            pair<double,double> pp;
            for (auto t: l) {
                int c = t.first, d = t.second;
                if (a == c)continue;
                pp.first = (b - d) / (c - a), pp.second = a * pp.first + b;
                p.insert(pp);
                
            }
            s+=p.size();
        }
        l.insert({a,b});
        s++;
    }
    cout<<s;
    return 0;
}

 

 
思路:只能从格子的左和上走到该格,且边界都只有一条路,更新到每个格子的方案数
int main(){
    cin.tie(0),cout.tie(0);
    cin>>n>>m;
    for(int i=1;i<=n;++i)a[i][1]=1;
    for(int i=1;i<=m;++i)a[1][i]=1;
    for(int i=2;i<=n;++i)
        for(int j=2;j<=m;++j)
            if(i%2!=0||j%2!=0)a[i][j]=a[i-1][j]+a[i][j-1];
    cout<<a[n][m];
    return 0;
}

 

 
思路:将每个结果转化成p进制数,乘数大于等于10也需转化
int main(){
    cin.tie(0),cout.tie(0);
    int p;
    vector<int>a;
    cin>>p;
    for(int i=1;i<p;++i){
        for(int j=1;j<=i;++j){
            if(i>=10){
                cout<<char('A'+i-10)<<'*';
            }
            else cout<<i<<'*';
            if(j>=10)cout<<char('A'+j-10)<<'=';
            else cout<<j<<'=';
            a.clear();
            int t=i*j;
            while(t){
                a.push_back(t%p);
                t/=p;
            }
            for(int k=a.size()-1;k>=0;--k)
            if(a[k]>=10)cout<<char('A'+a[k]-10);
            else cout<<a[k];
            if(j!=i)cout<<' ';
        }
        cout<<'\n';
    }
    return 0;
}

 

SMU Winter 2023 Round #3 (Div.2)

 
思路:当区间个数为偶数,异或和为0,为奇数,为从 l 开始与l奇偶性相同的数的异或和,树状数组分别记录奇数和偶数的异或和
typedef long long LL;
const int N = 2e5;
int n, m;
LL a[N],b[2][N];
int lowbit(int x){
    return x&-x;
}
void add(LL v, int x, int p){
    for(int i=x;i<=n;i+=lowbit(i))b[p][i]^=v;
}
LL Q(int x,int p){
    LL ans=0;
    for(int i=x;i;i-=lowbit(i))ans^=b[p][i];
    return ans;
}
int main() {
    cin>>n>>m;
    for(int i=1;i<=n;i++){
        cin>>a[i];
        add(a[i], i, i & 1);
    }
    for(int i=1;i<=m;i++){
        int p;
        LL l,r;
        cin>>p>>l>>r;
        if(p==1)add(a[l] ^ r, l, l & 1), a[l]=r;
        else printf("%lld\n",((l+r)&1)?0:(Q(r,r&1)^Q(l-1,r&1)));
    }
    return 0;
}

 

 
思路:暴力枚举所有情况
 
int main(){
    cin.tie(0),cout.tie(0);
    int n,m;
    cin>>m;
    while(m--){
        cin>>n;
        int a[105],res=0;
        for(int i=0;i<n;++i)
            cin>>a[i];
        for(int i=0;i<n;++i){
            for(int j=i;j<n;++j){
                for(int k=j;k<n;++k)
                if(a[i]+a[j]==a[k])res++;
            }
        }
        cout<<res<<'\n';
    }
    return 0;
}

 


思路:判断结果是否超出范围
int main(){
    cin.tie(0),cout.tie(0);
    int a,b;
    long long s;
    cin>>a>>b;
    s=pow(a,b);
    if(s>N||s<0)cout<<-1;
    else cout<<s;
    return 0;
}

 

 
思路:统计0~600分数的个数,按照分数线从大开始找
const int N=1e9;
int n,w,a[605],x,t;
int main(){
    cin.tie(0),cout.tie(0);
    cin>>n>>w;
    ::memset(a,0,sizeof a);
    for(int i=1;i<=n;++i){
        cin>>x;
        a[x]++;
        t=max(1,i*w/100);
        for(int j=600;j>=0;--j){
            if(a[j]!=0) t-=a[j];
            if(t<=0){
                cout<<j<<' ';break;
            }
        }
    }
    return 0;
}

 

 
思路:范围在最边上的四个矩形,判断w,h是否小于等于范围
int main(){
    cin.tie(0),cout.tie(0);
    long long a[2][4],w,h;
    for(int i=0;i<2;++i)
        for(int j=0;j<4;++j)
            cin>>a[i][j];
    long long x[4],y[4];
    x[0]=abs(a[0][0]-a[1][0]),x[1]=abs(a[0][2]-a[1][2]);
    y[0]=abs(a[0][3]-a[0][1]),y[1]=abs(a[0][3]-a[0][1]);
    x[2]=abs(a[0][2]-a[0][0]),y[2]=abs(a[0][1]-a[1][1]);
    x[3]=abs(a[0][2]-a[0][0]),y[3]=abs(a[0][3]-a[1][3]);
    cin>>w>>h;
    for(int i=0;i<4;++i){
        if(w<=x[i]&&h<=y[i]){
            cout<<"Yes";
            return 0;
        }
    }
    cout<<"No";
    return 0;
}

 

 
思路:最后一站人数为0,前一站为2*0+1,依次往前
int main(){
    cin.tie(0),cout.tie(0);
    int t,n;
    cin>>t;
    while(t--){
        cin>>n;
        int s=0;
        while(n--){
            s=2*s+1;
        }
        cout<<s<<'\n';
    }
    return 0;
}

 

 
思路:枚举出四个数字的段数
int main(){
    cin.tie(0),cout.tie(0);
    int n,s[10]={6,2,5,5,4,5,6,3,7,6};
    cin>>n;
    for(int i=0;i<3;++i){
            for(int j=0;j<=9;++j){
                if(i==0&&j==0)continue;
                if(i==2&&j>3)continue;
                for(int k=0;k<=5;++k){
                    for(int t=0;t<=9;++t)
                        if(s[i]+s[j]+s[k]+s[t]==n){
                            cout<<i<<j<<':'<<k<<t;
                            return 0;
                        }
                }
            }
    }
    cout<<"Impossible";
    return 0;
}

 

 
思路:01背包
const int N=1e3+5;
int f[N],w[105],v[105];
int main(){
    cin.tie(0),cout.tie(0);
    int t,m;
    cin>>t>>m;
    for(int i=1;i<=m;++i)cin>>v[i]>>w[i];
    for(int i=1;i<=m;++i){
        for(int j=t;j>=v[i];--j)
            f[j]=max(f[j],f[j-v[i]]+w[i]);
    }
    cout<<f[t];
    return 0;
}

 

 
思路:欧拉筛将求出范围内素数,反序可能比范围大,定范围时取r的位数的最大值
const int N=1e7;
long long l,r,cnt,p[N];
bool st[N];
int main(){
    cin.tie(0),cout.tie(0);
    cin>>l>>r;
    int a=0,c=r;
    while(c){
        a++;
        c/=10;
    }
    for(int i=2;i<=pow(10,a);++i){
        if(!st[i]){
            p[cnt++]=i;
        }
        for(int j=0;p[j]*i<=pow(10,a);++j){
            st[i*p[j]]=true;
            if(i%p[j]==0)break;
        }
    }
    int x[100000],q=0;
    for(int i=0;i<cnt;++i){//if(!st[p[i]])cout<<p[i]<<' ';
        if(p[i]>r)break;
        if(p[i]>=l){
            int t=p[i],k=0;
            while(t){
                k=k*10+t%10;
                t/=10;
            }
            if(!st[k])
                x[q++]=p[i];
        }
    }
    if(q==0){
        cout<<"No";
        return 0;
    }
    for(int i=0;i<q;++i)
    {
        cout<<x[i];
        if(i<q-1)cout<<',';
    }
    return 0;
}

 

 
 思路:求出范围内素数后判断是否满足回文条件
const int N=1e4+10;
long long l=11,r,cnt,p[N];
bool st[N];
int main(){
    cin.tie(0),cout.tie(0);
    cin>>r;
    int a=0,c=r;
    while(c){
        a++;
        c/=10;
    }
    for(int i=2;i<=r;++i){
        if(!st[i]){
            p[cnt++]=i;
        }
        for(int j=0;p[j]*i<=r;++j){
            st[i*p[j]]=true;
            if(i%p[j]==0)break;
        }
    }
    int b[100],k,res=0;
    for(int i=0;i<cnt;++i){
        if(p[i]>=l&&!st[p[i]]){
            int t=p[i];k=0;
            bool ok=true;
            while(t){
                b[k++]=t%10;
                t/=10;
            }
            for(int j=0;j<=(k-1)/2;++j){
                if(b[j]!=b[k-1-j]){
                    ok=false;break;
                }
            }
            if(ok)res++;
        }
    }
    cout<<res;
    return 0;
}

 

SMU Winter 2023 Round #4 (Div.2)

思路:枚举
int main(){
    cin.tie(0),cout.tie(0);
    int t,x;
    cin>>t;
    while(t--){
        cin>>x;
        int res=0;
        if(x<=12){
            for(int i=1;i<=x/2;++i)
                for(int j=1;j<=6;++j)
                    if(i+j==x){
                        res++;
                        break;
                    }
        }
        cout<<res<<'\n';
    }
    return 0;
}

 

思路:两轮过后锅里没有东西,统计下两轮的周期,再统计剩下的
int main(){
    cin.tie(0),cout.tie(0);
    int t,n,k,m;
    cin>>t;
    while(t--){
        set<int>se;
        cin>>n>>k>>m;
        vector<int>cnt(n,0),a(n);
        for(int i=0;i<n;++i)cin>>a[i];
        int b=m/n,d=m%(2*n);
        if(b<=1){
            for(int i=0;i<m;++i) {
                int j = i % n;
                if (se.count(a[j]) == 1) {
                    cnt[j]++;
                    se.erase(a[j]);
                } else {
                    se.insert(a[j]);
                }
            }
        }
        else{
            for(int i=0;i<2*n;++i){
                int j=i%n;
                if(se.count(a[j])==1){
                    cnt[j]++;se.erase(a[j]);
                }
                else{
                    se.insert(a[j]);
                }
            }
            for(int i=0;i<n;++i){
                cnt[i]*=(b/2);
            }
            for(int i=0;i<d;++i){
                int j=i%n;
                if(se.count(a[j])==1){
                    cnt[j]++;se.erase(a[j]);
                }
                else se.insert(a[j]);
            }
        }
        for(int i=0;i<n;++i){
            cout<<cnt[i];
            if(i!=n-1)cout<<' ';
        }
        cout<<'\n';
    }
    return 0;
}

 

Rock Paper Scissors
思路:以后者尽可能多得分来计算
int main(){
    cin.tie(0),cout.tie(0);
    int t;
    cin>>t;
    while(t--){
        ll a[3],b[3],res=0;
        for(int i=0;i<3;++i)
            cin>>a[i];
        for(int i=0;i<3;++i)
            cin>>b[i];
        for(int i=0;i<3;++i){
            int j=(i-1+3)%3;
            int mi=min(b[i],a[j]);
            b[i]-=mi,a[j]-=mi;
            res+=mi;
        }
        for(int i=0;i<3;++i){
            int mi=min(a[i],b[i]);
            a[i]-=mi,b[i]-=mi;
        }
        for(int i=0;i<3;++i)res-=a[i];
        cout<<res<<'\n';
    }
    return 0;
}

 

 
思路:每一种对应修改即可
int main(){
    cin.tie(0),cout.tie(0);
    int t;
    cin>>t;
    string a[8]={"chimasu","rimasu","mimasu","bimasu","nimasu","kimasu","gimasu","shimasu"};
    string b[8]={"tte","tte","nde","nde","nde","ite","ide","shite"};
    for(int i=0;i<t;++i){
        string c;
        cin>>c;//cout<<c<<'\n';
        for(int j=0;j<8;++j){
            int q=c.find(a[j]);
            if(c=="ikimasu"){
                cout<<"itte"<<'\n';break;
            }
            if(q!=-1){
                c.erase(q,c.size()-1);
                c+=b[j];
                cout<<c<<'\n';
                break;
            }
        }
    }
    return 0;
}

 

思路:从1开始枚举,每次找出+k且小于等于n的数,直到找出n个
int main(){
    cin.tie(0),cout.tie(0);
    int n,k,cnt=0;
    cin>>n>>k;
    for(int i=1;i<=n;++i){
        for(int j=0;;++j){
            if(j*k+i>n)break;
            cout<<j*k+i;
            cnt++;
            if(cnt!=n)cout<<' ';
        }
        if(cnt==n)break;
    }
    return 0;
}

 

思路:找出最大的登记时间间断,判断每个人能否在最大时间段内到达
int main(){
    cin.tie(0),cout.tie(0);
    ll n,k,x,p0;
    cin>>n>>k>>x>>p0;
    vector<double>h(n+5);
    vector<int> t(k);
    for(int i=0;i<n;++i){
        cin>>h[i];
        h[i]=x/h[i];
    }
    for(int i=0;i<k;++i){
        cin>>t[i];
    }
    int l,ma=-1;
    for(int i=0;i<k;++i){
        cin>>l;
        t[i]=l-t[i];
        ma=max(ma,t[i]);
    }
    int res=0;
    for(int i=0;i<n;++i){
        if(h[i]<=ma)res++;
    }
    cout<<res;
    return 0;
}

 

 
思路:每2*l的时间,一只蚂蚁可以各撞左右一次后回到原处,且一个2*l的时间内,一边最多撞n次;
可以模拟最后一轮蚂蚁的状态,每次用最后一只撞墙的蚂蚁时间更新撞墙后的蚂蚁的状态,直到没有蚂蚁撞墙,说明所有蚂蚁fall。
or分别算出左右撞碎的时间,若abs(t1-t2)<=l,则ans=max(t1,t2)+l;否则,ans=min(t1,t2)+2*l
#include<bits/stdc++.h>
#define int __int128
using namespace std;
typedef long long ll;
int read(){
    int x=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-') f=f*-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
void write(int x){
    if(x>9) write(x/10);
    putchar(x%10+'0');
}

int a[1000005];
int d[10000005];
int tr[1000005];
int tl[1000005];

const int mod=1e9+1;
signed main (){
    int n,aa,bb;
    n=read();aa=read();bb=read();
    for(int i=1;i<=n;++i)
    {
        a[i]=read();
    }
    for(int i=1;i<=n;++i)
        d[i]=read();
    int cnt=0,cnt1=0;
    tl[0]=0;
    tr[0]=0;
    for(int i=1;i<=n;++i)
    {
        if(d[i]==0)
        {
            tl[++cnt1]=a[i];
        }
    }
    for(int i=n;i>=1;--i)
    {
        if(d[i]==1)
        {
            tl[++cnt1]=(2ll*mod-a[i]);
            tr[++cnt]=(mod-a[i]);
        }
    }
    for(int i=1;i<=n;++i)
    {
        if(d[i]==0)
        {
            tr[++cnt]=a[i]+mod;
        }
    }
    int nn=n;
    int rallt,lallt;
    if(bb%nn!=0)
        rallt=(bb/(nn))*2ll*mod+tr[(bb-(bb/(nn))*nn)];
    else  rallt=((bb/(nn))-1)*2ll*mod+tr[nn];
    if(aa%nn!=0)
        lallt=(aa/(nn))*2ll*mod+tl[(aa-(aa/(nn))*nn)];
    else  lallt=((aa/(nn))-1)*2ll*mod+tl[nn];
    int ans=0;
    if(rallt>=lallt)
    {
        if(rallt>=lallt+mod)
        {
            ans=lallt+2*mod;
        }
        else {
            ans=rallt+mod;
        }
    }
    else {
        if(lallt>=rallt+mod)
            ans=rallt+2*mod;
        else ans=lallt+mod;
    }
    write(ans);putchar('\n');
    return 0;
}

 

思路:w的范围小,做100次bfs以点权为wi的所有点作为源点,再更新下每个点权不超过wj的最短路
const int N=1e5+10,inf=0x3f3f3f3f;
int n,m,q,w[N],dp[N][105];
vector<int>g[N];
queue<int>qe;
void bfs(int x){
    for(int i=1;i<=n;++i){
        if(w[i]==x){
            dp[i][x]=0;
            qe.push(i);
        }
    }
    while(!qe.empty()){
        int u=qe.front();qe.pop();
        for(auto v:g[u]){
            if(dp[v][x]==inf){
                dp[v][x]=dp[u][x]+1;
                qe.push(v);
            }
        }
    }
}
int main(){
    cin.tie(0),cout.tie(0);
    memset(dp,0x3f,sizeof dp);
    cin>>n>>m>>q;
    for(int i=1;i<=n;++i)cin>>w[i];
    while(m--){
        int u,v;
        cin>>u>>v;
        g[u].emplace_back(v);
        g[v].emplace_back(u);
    }
    for(int i=1;i<=100;++i)bfs(i);
    for(int i=1;i<=n;++i)
        for(int j=2;j<=100;++j)
            dp[i][j]=min(dp[i][j],dp[i][j-1]);
    while(q--){
        int p,t;
        cin>>p>>t;
        if(dp[p][t]==inf)cout<<-1<<'\n';
        else cout<<dp[p][t]<<'\n';
    }
}

 

E - Don't Really Like How The Story Ends
思路:要dfs的序列正好为1~n,当遍历到v时,看是否v+1与v相连,没有则加边,继续访问v+1
const int maxn =100100;
int t,n,m,ans,cnt;
vector<int>v[maxn];
void dfs(int x){
    if(x==n+1)return ;
    for(auto y:v[x]){
        if(y<cnt)continue;
        while(y>=cnt){
            if(y>cnt)ans++;
            dfs(cnt++);
        }
    }
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0),cout.tie(0);
    cin>>t;
    while(t--){
        cin>>n>>m;
        int x,y;
        for(int i=1;i<=n;++i)v[i].clear();
        for(int i=1;i<=m;++i){
            cin>>x>>y;
            v[x].push_back(y),v[y].push_back(x);
        }
        v[1].push_back(n+1);
        for(int i=1;i<=n;++i)sort(v[i].begin(),v[i].end());
        ans=0;
        cnt=2;
        dfs(1);
        cout<<ans<<'\n';
    }
    return 0;
}

 

 
思路:
1.当di<ai时,点i的代价是0;之后没加1,付出的代价就加1
2.(ui,vi)定向后可以恰好让ui和vi中的一个入度加1;考虑用费用流建模来描述过程。费用流图的点集由源点S,汇点T,m个表示原图中边的点A1,...,Am,n个表示原图中点的点B1,...,Bn组成;
3.对于每个Ai,S连接一条边到Ai,费用为0,容量为1;Ai连接两条边到Bui和Bvi,费用均为0,容量均为1;这个过程描述了一条边恰好能使ui和vi中的一个入读加1;
4.对于每个Bi,连接两条边到T;第一条的费用为0,容量为ai;第二条的费用为1,容量为无穷大;费用流增广的过程必定是先增广第一条,再增广第二条,这符合最开始对代价的描述;
5.这个图的最小费用最大流的费用为答案
 

 

 

题意:有一个均匀的三角形薄片 ABC,三个顶点各有一条细线连到一 个点 D 上。给定三边的长度和三条细线的长度,问提起 D 让三 角形自然落下到稳定状态时,三个顶点距离 D 的垂直距离。
 
思路:二分加贪心
1.二分能够击杀所有怪物的次数,得到每一种伤害使用的次数
贪心:

1)先把3用完:
先把3用在血量大于等于3且血量为奇数的怪物上,使其变成一个偶数且不浪费;
再把3用再血量大于等于6的怪物上(一次要用2个),保证这个怪物的血量还是偶数,且不浪费;
再把3用再血量最多的怪物上;
2)再把2用完:
把2用再血量大于等于2的怪物身上,保证不浪费;
再把2用再血量为1的怪物身上(只剩下1了);
3)最后把1用完;

posted @ 2023-01-09 19:34  bible_w  阅读(30)  评论(0编辑  收藏  举报