Educational Codeforces Round 81 (Rated for Div. 2)

比赛链接:https://codeforces.com/contest/1295

A. Display The Number

题意:火柴棍摆成数字的方式如下图所示。给你n根火柴棍问能摆出的最大数字。
在这里插入图片描述
解题思路:优先摆1,火柴棍不够的时候把第一个1变成7.

#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
using namespace std;
//#pragma GCC optimize(3,"Ofast","inline")
#define LL long long
//#define MT(a,b) memset(a,b,sizeof(a))
const int mod=1000007;
const int maxn=2e4+5;
const int ONF=-0x3f3f3f3f;
const int INF=0x3f3f3f3f;
int main (){
    int t;
    scanf("%d",&t);
    for (int i=1;i<=t;i++){
        int num;
        scanf("%d",&num);
        int tmp1=num/2;
        int tmp2=num-tmp1*2;
        if (tmp2==1) {
            printf("7");
            for (int j=2;j<=tmp1;j++) printf("1");
        } else for (int j=1;j<=tmp1;j++) printf("1");
        printf("\n");
    }
    return 0;
}

B. Infinite Prefixes

题意:给一个由n个01数字构成的串s。可以链接无限个s变成t(sss)。0的数量减去1的数量叫平衡值。问t中有多少个前缀,其中平衡值等于x。(空缀算其中一个前缀)
解题思路:设bal[i]储存s中每个位置的平衡值。设有k个完整s构成t。则有k·bal[len]+bal[i]==x。可以化简为k==(x-bal[i])/bal[len]。求k可以为正整数的可能情况。
记得考虑特殊情况bal[len]==0时。如果s中有bal[i]==x输出-1,否则输出0.

#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
using namespace std;
//#pragma GCC optimize(3,"Ofast","inline")
#define LL long long
#define MT(a,b) memset(a,b,sizeof(a))
const int mod=1000007;
const int maxn=2e5+5;
const int ONF=-0x3f3f3f3f;
const int INF=0x3f3f3f3f;
int bal[maxn];
char str[maxn];
int main (){
    int t;
    scanf("%d",&t);
    while (t--){
        LL len,x;
        scanf("%lld%lld",&len,&x);
        bal[0]=0;
        scanf("%s",str);
        for (int i=1;i<=len;i++){
            int tmp;
            tmp=str[i-1]-'0';
            bal[i]=bal[i-1];
            if (tmp==0) bal[i]++;
            else bal[i]--;
        }
        if (bal[len]==0){
            int flag=0;
            for (int i=0;i<=len;i++){
                if (bal[i]==x) {
                    flag=1;
                    break;
                }
            }
            if (flag) printf("-1\n");
            if (flag==0) printf("0\n");
        }
        else{
            int ans=0;
            for (int i=1;i<=len;i++){
                if ((x-bal[i])%bal[len]==0&&(x-bal[i])/bal[len]>=0)
                    ans++;
            }
            if (x==0) ans++;
            printf("%d\n",ans);
        }
    }
    return 0;
}

C. Obtain The String

题意:给你一个字符串s和一个空串x。你能从s中选择任意字串加在x后方。问最少多少次操作能构成目标串t。如果无法构成输出-1.
解题思路:先判断t里有没有s里没有的字符。预处理字符串s,找出s中每个位置的下一个目标字母的最近位置。遍历t中每一个字母,如果可以在s中找到下一个,就继续,并更新位置。找不到就从s开头找。

#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
using namespace std;
//#pragma GCC optimize(3,"Ofast","inline")
#define LL long long
#define MT(a,b) memset(a,b,sizeof(a))
const int mod=1000007;
const int maxn=1e5+5;
const int ONF=-0x3f3f3f3f;
const int INF=0x3f3f3f3f;
char s[maxn],t[maxn];
bool have[30];
int dp[maxn][30];//s中第i个位置到字母的消耗
int main (){
    int T;
    scanf("%d",&T);
    while (T--){
        scanf("%s%s",s,t);
        MT(have, false);
        int len_s=strlen(s),len_t=strlen(t);
        for (int i=0;i<26;i++){
            dp[len_s][i]=-1;
            for (int j=len_s-1;j>=0;j--){
                have[s[j]-'a']= true;
                if (s[j]-'a'==i) dp[j][i]=j;
                else dp[j][i]=dp[j+1][i];
            }
        }
        int ans=1,flag=1,pos=0;
        for (int i=0;i<len_t;i++){
            if (!have[t[i]-'a']) {
                flag=0;
                break;
            }
            pos=dp[pos][t[i]-'a'];
            if (pos==-1){
                ans++;
                pos=dp[0][t[i]-'a'];
            }
            pos++;
        }
        if (flag) printf("%d\n",ans);
        else printf("-1\n");
    }
    return 0;
}

D. Same GCDs

题意:给两个数字a,m(1≤a<m≤1010).
求有多少个x满足(0≤x<m)且gcd(a,m)=gcd(a+x,m)
解题思路:设t=gcd(a+x,m).
则有gcd((a+x)/t,m/t)=1.设L=a/t,R=m/t。gcd(L+x/t,R)=1.问题转化成求[L,L+R-1]区间中和R有多少数互质。
[L,L+R-1]区间可以转化为求[L,R]+[R+1,L+R-1].
设k∈[1,L-1] 有gcd(k,R)=gcd(k+R,R)所以求[R+1,L+R-1]相当于求区间[1,L-1].
所以区间[L,L+R-1]相当于求区间[1,R].
所以答案为φ(m/t)

#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
using namespace std;
//#pragma GCC optimize(3,"Ofast","inline")
#define LL long long
#define MT(a,b) memset(a,b,sizeof(a))
const int mod=1000007;
const int maxn=1e5+5;
const int ONF=-0x3f3f3f3f;
const int INF=0x3f3f3f3f;
LL olhs(LL n){
    LL ans=n;
    for (LL i=2;i*i<=n;i++){
        if (n%i==0){
            ans-=ans/i;
            while (n%i==0){
                n/=i;
            }
        }
    }
    if (n>1) ans -=ans/n;
    return ans;
}
LL gcd(LL x,LL y){ return y==0?x:gcd(y,x%y);}
int main (){
    int T;
    scanf("%d",&T);
    while (T--){
        LL a,m;
        scanf("%lld%lld",&a,&m);
        LL t=gcd(a,m);
        printf("%lld\n",olhs(m/t));
    }
    return 0;
}

E. Permutation Separation

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值