比赛链接: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;
}