四川大学第二届SCUACM新生赛(同步赛)部分题解

A. 丁姐姐喜欢Fibonacci

签到题,注意输出格式即可。

#include<bits/stdc++.h>
using namespace std;
int main(){
    long long n;
    while(scanf("%lld",&n) !=EOF){
	    if(n%3==0) printf("\"odd\"");
	    else printf("\"even\"");
	    puts("");
    }
    return 0;
}

B.丁姐姐喜欢LCS

签到题,用KMP预处理出B串的nxt数组,再用A串在上面匹配即可。

#include<bits/stdc++.h>
using namespace std;
const int MAXN = 20050;
char s[MAXN],t[MAXN];
int nxt[MAXN];
int main(){
    while(~scanf("%s%s",s+1,t+1)){
        int n=strlen(s+1),m=strlen(t+1);
        int j=0;
        nxt[0]=nxt[1]=0;
        for(int i=2;i<=m;i++){
            while(j && t[i]!=t[j+1]) j=nxt[j];
            if(t[i]==t[j+1]) ++j;
            nxt[i]=j;
        }
        for(int i=max(n-m+1,1);i<=n;i++){
            while(j && s[i]!=t[j+1]) j=nxt[j];
            if(s[i]==t[j+1]) ++j;
        }
        if(j==0) printf("\"NULL!\"");
        else for(int i=1;i<=j;i++) putchar(t[i]);
        puts("");
    }
    return 0;
}

C.俏兔子大战傻贼鹰-Easy Version

简单的模拟,胡牌只有两种类型,分别判断一下即可。

#include<bits/stdc++.h>
using namespace std;
string op;
inline bool solve(int T){
    string ss; cin>>ss;
    map<string,int> mp;
    for(int i=0;i<(int)ss.length();i++)
        if(ss[i]==op[0])
            return false;//还没缺
    for(int i=0;i<(int)ss.length();i+=2)
        mp[ss.substr(i,2)]++;
    int cnt = 0;
    for(map<string,int>::iterator it=mp.begin();it!=mp.end();it++)
        if(it->second % 2 == 0)
            cnt++;
    if(cnt==(int)mp.size()) return true;//七对子
    int cnt1 = 0,cnt2 = 0;
    for(map<string,int>::iterator it=mp.begin();it!=mp.end();it++){
        if(it->second%3==0) cnt1++;
        else if(it->second%2==0) cnt2++;
    }
    if(cnt1==4 && cnt2==1) return true;//对对胡
    return false;
}
int main(){
    int n;
    while(cin>>n){
        cin>>op;
        for(int i=1;i<=n;i++) cout<<(solve(i) ? "Yes":"No")<<endl;
    }
    return 0;
}

D.俏兔子大战傻贼鹰-Hard Version

比上一道题的模拟情况多了一种,只是需要细心一点。

#include<bits/stdc++.h>
using namespace std;
const int MAXN = 15;
int s[MAXN],t[MAXN],w[MAXN];
string ss;
int main(){
    int n; char ch;
    while(cin>>n){
        cin>>ch;
        for(int T=0;T<n;T++){
            cin>>ss;
            bool ok=true;
            for(int i=0;i<=(int)ss.length();i++) if(ss[i]==ch) { ok=false;break; }
            if(!ok) { puts("No");continue; }
            for(int i=1;i<=10;i++) s[i]=t[i]=w[i]=0;
            for(int i=0;i<(int)ss.length();i+=2){
                if(ss[i+1]=='S') s[ss[i]-'0']++;
                else if(ss[i+1]=='T') t[ss[i]-'0']++;
                else if(ss[i+1]=='W') w[ss[i]-'0']++;
            }
            int sum=0,cnt=0;
            for(int i=1;i<=9;i++){
                if(s[i]==2) sum++;
                if(t[i]==2) sum++;
                if(w[i]==2) sum++;
            }
            if(sum==7) { puts("Yes");continue; }
            int jiang=0;
            bool op = true;
            for(int i=1;i<=9;i++){
                while(s[i]>0 && s[i+1]>0 && s[i+2]>0)
                    s[i]--,s[i+1]--,s[i+2]--;
                if(s[i]!=0 && s[i]!=3){
                    if(s[i]==2 && !jiang)
                        s[i]-=2,jiang++;
                    else { op=false;break; }
                }
                while(t[i]>0 && t[i+1]>0 && t[i+2]>0)
                    t[i]--,t[i+1]--,t[i+2]--;
                if(t[i]!=0 && t[i]!=3){
                    if(t[i]==2 && !jiang)
                        t[i]-=2,jiang++;
                    else { op=false;break; }
                }
                while(w[i]>0 && w[i+1]>0 && w[i+2]>0)
                    w[i]--,w[i+1]--,w[i+2]--;
                if(w[i]!=0 && w[i]!=3){
                    if(w[i]==2 && !jiang)
                        w[i]-=2,jiang++;
                    else { op=false;break; }
                }
            }
            if(op && jiang==1) puts("Yes");
            else puts("No");
        }
    }
    return 0;
}

E.[模板]欧拉筛

这真的是模板题,只是很多人容易将数组开到1E8,其实只需要开到P就好了,因为超过P以后,阶乘就一直等于0了。

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int MAXN = 2e5+50;
inline int read(){
    int x=0,f=1; char ch=getchar();
    while(ch<'0' || ch>'9'){ if(ch=='-') f=-1; ch = getchar(); }
    while(ch>='0' && ch<='9') x=(x<<1)+(x<<3)+ch-48,ch=getchar();
    return x*f;
}
int prime[MAXN+50],tot;
bool vis[MAXN+50];
int fac[MAXN+50];
inline void Init(){
    for(int i=2;i<=MAXN;i++){
        if(!vis[i]) prime[++tot]=i;
        for(int j=1;j<=tot && i*prime[j]<=MAXN;j++){
            vis[i*prime[j]]=1;
            if(i%prime[j]==0) break;
        }
    }
}
signed main(){
    Init();
    fac[1]=1;
    int T=read();
    while(T--){
        int n=read(),P=read();
        int res=0;
        for(int i=2;i<P;i++) fac[i]=fac[i-1]*i%P;
        for(int i=1;prime[i]<=n && prime[i]<P;i++)
            res = (res+fac[prime[i]])%P;
        printf("%lld\n",res);
    }
    return 0;
}

F.[模板]后缀自动机

这道题我没用后缀自动机,其实我们只需要找到S中最小的后缀,我们记这个后缀的第一个字符的位置位pos,然后用这个后缀去和T的每一个前缀比较,然后再想想,要满足条件,T的第一个字符也应该大于pos这个后缀,所以T[0]一定要大于S[pos],然后既然第一个字符已经比S[pos]大了,后面也不用再比较了,显然满足要求。
求最小后缀用最小表示法就够了。

#include<bits/stdc++.h>
using namespace std;
const int MAXN = 2e5+50;
char s[MAXN],t[MAXN];
int ls,lt;
inline int solve(){
    int i=0,j=1;
    while(i<ls && j<ls){
        int k=0;
        while(s[(i+k)%ls]==s[(j+k)%ls] && k<ls) k++;
        if(k==ls) break;
        if(s[(i+k)%ls]>s[(j+k)%ls]) i=i+k+1;
        else j=j+k+1;
        if(i==j) j++;
    }
    return min(i,j);
}
int main(){
    int T; scanf("%d",&T);
    while(T--){
        scanf("%s%s",s,t);
        ls=strlen(s),lt=strlen(t);
        int pos=solve();
        bool ok = true;
        if(s[pos]>=t[0]) ok=false;
        if(!ok) puts("N0");
        else puts("YE5");
    }
    return 0;
}

I.排序

跟着要求写就好了,没什么坑

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int MAXN = 55;
struct node{
    string name;
    int ac,sum,fa[15],cnt[15],vis[15];
}a[MAXN];
inline bool cmp(node x,node y){
    if(x.ac != y.ac) return x.ac > y.ac;
    else if(x.ac==y.ac){
        if(x.sum == y.sum) return x.name < y.name;
        return x.sum < y.sum;
    }
}
inline void Init(){
    for(int i=0;i<=50;i++){
        a[i].ac = a[i].sum = 0;
        memset(a[i].fa,0,sizeof(a[i].fa));
        memset(a[i].cnt,0,sizeof(a[i].cnt));
        memset(a[i].vis,0,sizeof(a[i].vis));
    }
}
int main(){
    ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
    int T; cin>>T;
    while(T--){
        Init();
        int n,m; cin>>n>>m;
        map<string,int> mp;
        for(int i=0;i<m;i++){
            cin>>a[i].name; mp[a[i].name] = i;
        }
        int Q; cin>>Q;
        while(Q--){
            string id,ans;
            int time; char ch;
            cin>>id>>time>>ch>>ans;
            if(a[mp[id]].vis[ch-'A']) continue;
            else if(ans=="Accepted"){
                a[mp[id]].vis[ch-'A']=time;
                a[mp[id]].cnt[ch-'A']++;
                a[mp[id]].ac++;
                a[mp[id]].fa[ch-'A']+=time;
                a[mp[id]].sum += a[mp[id]].fa[ch-'A'];
            }
            else if(ans=="Compilation-Error") continue;
            else{
                a[mp[id]].cnt[ch-'A']++;
                a[mp[id]].fa[ch-'A']+=20;
            }
        }
        sort(a,a+m,cmp);
        int now=1;
        for(int i=0;i<m;i++){
            if(i!=0 && a[i].ac==a[i-1].ac && a[i].sum==a[i-1].sum) cout<<now;
            else { now=i+1; cout<<now; }
            cout<<' '<<a[i].name<<' '<<a[i].ac<<' '<<a[i].sum<<' ';
            for(int j=0;j<n;j++){
                if(a[i].vis[j]!=0) cout<<'+'<<a[i].cnt[j]<<'('<<a[i].vis[j]<<')'<<' ';
                else cout<<'-'<<a[i].cnt[j]<<' ';
            }
            cout<<endl;
        }
        if(T) cout<<endl;
    }
    return 0;
}

J.n=abc

暴力枚举

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int INF = 0x3f3f3f3f;
int main(){
    int T,a,b,c; cin>>T;
    while(T--){
        int n; cin>>n;
        int mi = INF;
        for(int i=2;i<=n-1;i++){
            if(n%i==0){
                int m = n/i;
                for(int j=i;j<=m/j+1;j++){
                    if(m%j==0 && j<=m/j){
                        if(m/j - i < mi){
                            a = i,b = j,c = m/j;
                            mi = m/j-i;
                        }
                    }
                }
            }
        }
        if(mi == INF) puts("No solution");
        else printf("%d=%d*%d*%d\n",n,a,b,c);
    }
    return 0;
}

K.梅森素数

打表即可

#include<bits/stdc++.h>
using namespace std;
int main(){
    cout<<3<<' '<<7<<' '<<31<<' '<<127<<' '<<8191<<endl;
    return 0;
}

L.双流机场

判断行和列是不是全部向一个方向,再判断四个角落即可

#include<bits/stdc++.h>
using namespace std;
const int MAXN = 1e5+50;
inline int read(){
    int x=0,f=1; char ch=getchar();
    while(ch<'0' || ch>'9'){ if(ch=='-') f=-1; ch = getchar(); }
    while(ch>='0' && ch<='9') x=(x<<1)+(x<<3)+ch-48,ch=getchar();
    return x*f;
}
char s[MAXN],t[MAXN];
int n,m;
inline bool solve(){
    bool op = false;
    for(int i=2;i<=n;i++) if(s[i]!=s[i-1]) { op=true;break; }
    if(!op) return false;
    op=false;
    for(int i=2;i<=m;i++) if(t[i]!=t[i-1]) { op=true;break; }
    if(!op) return false;
    if(s[1]=='1' && t[1]=='0') return false;
    if(s[n]=='1' && t[1]=='1') return false;
    if(s[1]=='0' && t[m]=='0') return false;
    if(s[n]=='0' && t[m]=='1') return false;
    return true;
}
int main(){
    int T=read();
    while(T--){
        n=read(),m=read();
        scanf("%s%s",s+1,t+1);
        cout<<(solve() ? "Happy":"Sad")<<endl;
    }
    return 0;
}

M.lglg说要有题,于是便有了题。

题目要求求出 l n l n ( x ) lnln(x) lnln(x),只需要在前面精度不高的时候通过计算求出,后面套用公式即可

#include<bits/stdc++.h>
using namespace std;
const int MAXN = 1e6;
bool vis[MAXN+20];
int prime[MAXN+20],tot;
inline void Init(){
    for(int i=2;i<=MAXN;i++){
        if(!vis[i]) prime[++tot]=i;
        for(int j=1;j<=tot && i*prime[j]<=MAXN;j++){
            vis[i*prime[j]]=1;
            if(i%prime[j]==0) break;
        }
    }
}
int main(){
    Init();
    int T; scanf("%d",&T);
    while(T--){
        int n; scanf("%d",&n);
        if(n>1000000) printf("%.0f\n",log(log((double)(n))));
        else{
            double res = 0.0;
            for(int i=1;prime[i]<=n;i++) res += 1.0/(double)prime[i];
            printf("%.0f\n",res);
        }
    }
    return 0;
}
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值