The 10th Shandong Provincial Collegiate Programming Contest

The 10th Shandong Provincial Collegiate Programming Contest

A - Calandar

思路:将日期转换为天数,求出差值对5取模

#include<bits/stdc++.h>
using namespace std;
#define int long long
//#define int __int128
typedef pair<int,int>PII;
typedef pair<string,int>PSI;
typedef pair<string,string>PSS;
const int N=2e5+5,INF=0x3f3f3f3f,Mod=1e9+7,mod=998244353;
const double eps=1e-6;

map<string,int>si;
string is[5];
void init(){
    si["Monday"]=0;
    si["Tuesday"]=1;
    si["Wednesday"]=2;
    si["Thursday"]=3;
    si["Friday"]=4;
    is[0]="Monday";
    is[1]="Tuesday";
    is[2]="Wednesday";
    is[3]="Thursday";
    is[4]="Friday";
}
void solve(){
    int y1,m1,d1,y2,m2,d2;
    string s1,s2;
    cin>>y1>>m1>>d1>>s1>>y2>>m2>>d2;
    int x1=y1*12*30+m1*30+d1;
    int x2=y2*12*30+m2*30+d2;
    x2-=x1;
    int p=si[s1];
    p+=x2;
    p=(p%5+5)%5;
    cout<<is[p]<<'\n';
}
signed main(){
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    int t=1;
    init();
    cin>>t;
    while(t--){
        solve();
    }
    return 0;
}
View Code

 

 B - Flipping Game

思路:将001→100,看作101→000,实际是一样的,变为最终状态只需要对第一和第三个操作一次即可,过程中的其他次数实际一样;所以初始串可转变为两串异或后的状态;

考虑dp来写,f[i][j]表示前i轮,且第i轮有j盏灯亮的方案数;

x表示上一轮1的数目,l表示这一轮对0操作的数目,则这一轮对1操作的数目为m-l;

对上一轮操作后,j=x+l-(m-l),即x=m+j-2l

从上一轮的n-x中选l个0,有C(n-x,l)种可能;从上一轮的x中选m-l个1,有C(x,m-l)种可能;

且保证l<=n-x和m-l<=x,则l<=j

则有f[i][j]+=f[i-1][x]*C(n-x,l)*C(x,m-l)

 

#include<bits/stdc++.h>
using namespace std;
#define int long long
//#define int __int128
typedef pair<int,int>PII;
typedef pair<string,int>PSI;
typedef pair<string,string>PSS;
const int N=2e5+5,INF=0x3f3f3f3f,Mod=1e9+7,mod=998244353;
const double eps=1e-6;

int c[105][105];
void init(){
    for(int i=0;i<=100;++i){
        for(int j=0;j<=i;++j){
            if(!j)c[i][j]=1;
            else c[i][j]=(c[i-1][j]+c[i-1][j-1])%mod;
        }
    }
}
void solve(){
    int n,k,m;cin>>n>>k>>m;
    string s1,s2;cin>>s1>>s2;
    int cnt1=0;
    for(int i=0;i<n;++i)
        cnt1+=s1[i]!=s2[i];
    vector<vector<int>>f(k+1,vector<int>(n+1,0));
    f[0][cnt1]=1;
    for(int i=1;i<=k;++i)
        for(int j=0;j<=n;++j)
            for(int l=0;l<=j&&l<=m;++l){
                int x=m+j-2*l;
                if(x<0||x>n||l>n-x)continue;
                f[i][j]=(f[i][j]+f[i-1][x]*c[n-x][l]%mod*c[x][m-l]%mod)%mod;
            }
    cout<<f[k][0]<<'\n';
}
signed main(){
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    int t=1;
    init();
    cin>>t;
    while(t--){
        solve();
    }
    return 0;
}
View Code

 

C - Wandering Robot

思路:每操作n次,发现增量都是相同的,增量为第一轮操作第n次的下标(a,b);对于同一个操作,每次的距离一定大于上一次,那么只需要找到第1轮和第k轮操作后的距离的最大值

#include<bits/stdc++.h>
using namespace std;
#define int long long
//#define int __int128
typedef pair<int,int>PII;
typedef pair<string,int>PSI;
typedef pair<string,string>PSS;
const int N=2e5+5,INF=0x3f3f3f3f,Mod=1e9+7,mod=998244353;
const double eps=1e-6;


void init(){

}
void solve(){
    int n,k;cin>>n>>k;
    string s;cin>>s;
    int ans=0;
    vector<int>x(n+1),y(n+1);
    for(int i=1;i<=n;++i){
        x[i]=x[i-1],y[i]=y[i-1];
        if(s[i-1]=='U')y[i]++;
        else if(s[i-1]=='D')y[i]--;
        else if(s[i-1]=='L')x[i]--;
        else x[i]++;
        ans=max(ans,abs(x[i])+abs(y[i]));
    }
    for(int i=1;i<=n;++i){
        ans=max(ans,abs(x[i]+x[n]*(k-1))+abs(y[i]+y[n]*(k-1)));
    }
    cout<<ans<<'\n';
}
signed main(){
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    int t=1;
    init();
    cin>>t;
    while(t--){
        solve();
    }
    return 0;
}
View Code

 

D - Game on a Graph

思路:一个连通图最少要n-1条边,所以最大的操作次数为x=m-(n-1),即输的人为x%k

#include<bits/stdc++.h>
using namespace std;
#define int long long
//#define int __int128
typedef pair<int,int>PII;
typedef pair<string,int>PSI;
typedef pair<string,string>PSS;
const int N=2e5+5,INF=0x3f3f3f3f,Mod=1e9+7,mod=998244353;
const double eps=1e-6;


void init(){

}
void solve(){
    int k;cin>>k;
    string s;cin>>s;
    int n,m;cin>>n>>m;
    for(int i=0,u,v;i<m;++i)cin>>u>>v;
    int p=m-(n-1);
    if(s[p%k]=='1')cout<<2<<'\n';
    else cout<<1<<'\n';
}
signed main(){
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    int t=1;
    init();
    cin>>t;
    while(t--){
        solve();
    }
    return 0;
}
View Code

 

F - Stones in the Bucket

思路:总数为all时,每个人为all/n是最优情况,则取最近的n的倍数(倍数越小说明第一次操作会多n,且小于平均值的数最多会少n次操作,并不会减少操作,可能会增加);第一种操作次数即为多出n的倍数的石头,第二种由于多出和少出平均值的数量是相等的,算少的即可

#include<bits/stdc++.h>
using namespace std;
#define int long long
//#define int __int128
typedef pair<int,int>PII;
typedef pair<string,int>PSI;
typedef pair<string,string>PSS;
const int N=2e5+5,INF=0x3f3f3f3f,Mod=1e9+7,mod=998244353;
const double eps=1e-6;


void init(){

}
void solve(){
    int n,all=0;cin>>n;
    vector<int>ve(n);
    for(int i=0;i<n;++i)cin>>ve[i],all+=ve[i];
    int k=all/n;
    int ans=all%n;//第一种
    for(int i=0;i<n;++i)//第二种
        if(ve[i]<k)ans+=k-ve[i];
    cout<<ans<<'\n';
}
signed main(){
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    int t=1;
    init();
    cin>>t;
    while(t--){
        solve();
    }
    return 0;
}
View Code

 

H - Tokens on the Segments

思路:按左右端点排序,优先选择右端点小的,用堆维护

#include<bits/stdc++.h>
using namespace std;
#define int long long
//#define int __int128
typedef pair<int,int>PII;
typedef pair<string,int>PSI;
typedef pair<string,string>PSS;
const int N=2e5+5,INF=0x3f3f3f3f,Mod=1e9+7,mod=998244353;
const double eps=1e-6;


void init(){

}
void solve(){
    int n;cin>>n;
    vector<PII>ve(n);
    for(int i=0;i<n;++i)cin>>ve[i].first>>ve[i].second;
    sort(ve.begin(),ve.end());
    priority_queue<int,vector<int>,greater<int>>q;
    int idx=0,l,ans=0;
    while(1){
        while(q.size()&&q.top()<l)q.pop();
        if(q.empty()){
            if(idx>=n)break;
            l=ve[idx].first;
        }else{
            ans++;q.pop();
            l++;
        }
        while(idx<n&&ve[idx].first<=l){
            q.push(ve[idx].second);idx++;
        }
    }
    cout<<ans<<'\n';
}
signed main(){
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    int t=1;
    init();
    cin>>t;
    while(t--){
        solve();
    }
    return 0;
}
View Code

 

K - Happy Equation

思路:a,x的奇偶性相同(因为都对偶数取模),且打表得出a为奇数时,答案为1。(¿)

a为偶数时,令 a=t1*2q   → ax=t1x*2qx

若axmod2p为0,则qx>=p,x>=p/q;由于q>=1(a为偶数),则x>=p

x与a同为偶数,令x'=t2*2k → x'a=t2a*2ka

若x'amod2p为0,则ka>=p,k>=p/a(上取)=k'

在[p,2p]中,x取2k'的倍数即可满足xamod2p为0,个数有2p-k'-(p-1)/2k'

在[1,p)中,枚举x即可;(p<=30)

#include<bits/stdc++.h>
using namespace std;
#define int long long
//#define int __int128
typedef pair<int,int>PII;
typedef pair<string,int>PSI;
typedef pair<string,string>PSS;
const int N=2e5+5,INF=0x3f3f3f3f,Mod=1e9+7,mod=998244353;
const double eps=1e-6;
int mmod;
int ksm(int x,int y){
    int res=1;
    while(y){
        if(y&1)res=res*x%mmod;
        x=x*x%mmod;
        y>>=1;
    }
    return res;
}
void solve(){
    int a,p;cin>>a>>p;
    mmod=1<<p;
    if(a&1){
        cout<<"1\n";return ;
    }
    int ans=0;
    for(int i=1;i<p;++i)
        ans+=ksm(a,i)==ksm(i,a);
    int y=(p+a-1)/a;
    ans+=(1<<(p-y))-(p-1)/(1<<y);
    cout<<ans<<'\n';
}
signed main(){
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    int t=1;
    //init();
    cin>>t;
    while(t--){
        solve();
    }
    return 0;
}
View Code

 

L - Median

思路:一条关系可以看作一条有向边,由大的指向小的,得到一张有向图,先判断有无环,有环说明情况不存在全为0;可用bfs或dfs判断,同时记录该点的前继和后继;若该点为中位点,说明该点的前继和后继都不超过n/2

#include<bits/stdc++.h>
using namespace std;
#define int long long
//#define int __int128
typedef pair<int,int>PII;
typedef pair<string,int>PSI;
typedef pair<string,string>PSS;
const int N=2e5+5,INF=0x3f3f3f3f,Mod=1e9+7,mod=998244353;
const double eps=1e-6;


void init(){

}
void solve(){
    int n,m;cin>>n>>m;
    vector<int>g[n+1],vis(n+1,0),up(n+1),low(n+1);
    for(int i=0,u,v;i<m;++i){
        cin>>u>>v;
        g[u].push_back(v);
    }
    auto bfs=[&](int u){
        queue<int>q;
        q.push(u);vis[u]=u;
        while(q.size()){
            int t=q.front();q.pop();
            for(auto v:g[t]){
                if(v==u)return false;
                if(vis[v]==u)continue;
                vis[v]=u;q.push(v);
                low[u]++,up[v]++;
            }
        }
        return true;
    };
    for(int i=1;i<=n;++i){
        if(!bfs(i)){
            for(int j=1;j<=n;++j)cout<<"0";cout<<'\n';
            return ;
        }
    }
    for(int i=1;i<=n;++i)
        if(low[i]<=n/2&&up[i]<=n/2)cout<<"1";
        else cout<<"0";cout<<'\n';
}
signed main(){
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    int t=1;
    init();
    cin>>t;
    while(t--){
        solve();
    }
    return 0;
}
View Code

 

M - Sekiro

思路:当n<=1时,答案就为n

#include<bits/stdc++.h>
using namespace std;
#define int long long
//#define int __int128
typedef pair<int,int>PII;
typedef pair<string,int>PSI;
typedef pair<string,string>PSS;
const int N=2e5+5,INF=0x3f3f3f3f,Mod=1e9+7,mod=998244353;
const double eps=1e-6;


void init(){

}
void solve(){
    int n,k;cin>>n>>k;
    while(k&&n>1){
        n=(n+1)/2;k--;
    }
    cout<<n<<'\n';
}
signed main(){
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    int t=1;
    init();
    cin>>t;
    while(t--){
        solve();
    }
    return 0;
}
View Code

 

posted @ 2023-08-01 21:32  bible_w  阅读(25)  评论(0编辑  收藏  举报