CF Educational Round 81 A-D 题解
A. Display the number
https://codeforces.com/contest/1295/problem/A
题目大意:
显示0-9这十个数字分别需要6,2,5,5,4,5,6,3,7,6个亮块。
现在你有n个亮块,需要你输出你用这n个亮块能组成的最大数字。
显然我们需要保证数字的位数最多,这样数也就越大。
那么如果n是偶数,那就输出n/2个1
否则输出一个7,再输出(n-3)/2个1
#include<bits/stdc++.h> using namespace std; int main() { int t; cin>>t; while(t--){ int n; cin>>n; if(n%2==0){ for(int i=0;i<n/2;i++) cout<<'1'; cout<<endl; continue; } if(n==3){ cout<<'7'<<endl; continue; } if(n%2!=0&&n!=3){ cout<<'7'; for(int i=0;i<n/2-1;i++) cout<<'1'; cout<<endl; continue; } } return 0; }
B. Infinite Prefixes
https://codeforces.com/contest/1295/problem/B
题目大意:
给你一个01串s和两个整数n,t
n是串s的长度,t是期望的number of(0) - number of(1). (题目中称为balance)
现在你可以不断的重复s得到新的字符串z,求能满足0的个数减去1的个数等于t的字符串z长度的个数,如果有无限个,那就输出-1.
有点绕,给个例子解释下
样例:6 10 010010
把s不断重复,比如当z=010010 010010 010010 010010 0100 的时候,t=10,满足题意,这个时候length=28.
同理,length=30,32的时候也满足题意,所以答案输出3.
思路的话,可以记录在一个循环内每个位置的balance。
然后计算一下整个串的balance,这里记做cyc
显然这个串是通过自我拼接形成的,所以在新串的每个点,它的balance一定和初始串相应位置的balance对于cyc同余。
那就直接判断(balance-t)/cyc是不是非负整数就可以了,是的话ans+1,否则continue。
当cyc=0而且初始计算出的balance = t的位置存在的话,输出-1.
#include<bits/stdc++.h> using namespace std; int s[100005]; int main() { int t; cin>>t; while(t--) { int n,x; cin>>n>>x; int s0=0,s1=0; for(int i=0; i<n; i++) { char r; cin>>r; if(r=='0') s0++; else s1++; s[i]=s0-s1; } int ans=0; if(x==0) ans++; int cyc=s0-s1; //cout<<cyc<<endl; if(cyc!=0) { for(int i=0; i<n; i++) { if((x-s[i])/cyc>=0&&(x-s[i])%cyc==0) ans++; //注意一定是非负整数,如果没判等于0的话就把初始=t的情况漏了,最后会fst。(别问我怎么知道的) } cout<<ans<<endl; } bool flag=true; if(cyc==0) { for(int i=0; i<n; i++) { if(s[i]==x) { cout<<"-1"<<endl; flag=false; break; } } if(flag==true) { cout<<"0"<<endl; continue; } continue; } } return 0; }
C.Obtain The String
https://codeforces.com/contest/1295/problem/C
题目大意:给你两个串s,t和一个空串z,每次对z append一个s的子串,问至少要多少次操作才能让z变成t,如果不行就输出-1.
s和t的长度规模1e5
这个题有两个做法
先介绍官方的O(n)做法
预处理一个next[i][j]数组,表示在s串中离i位置之后最近的j字符的位置 从后往前dp处理
具体看代码吧 有注释
//悬线dp,序列自动机 #include<bits/stdc++.h> using namespace std; int T; string s,t; int nxt[100005][26]; int main(){ ios::sync_with_stdio(0); cin.tie(0),cout.tie(0); cin>>T; while(T--){ bool flag=true; cin>>s; cin>>t; int lens=s.length(),lent=t.length(); for(int j=0;j<26;j++) nxt[lens][j]=lens; for(int i=lens-1;i>=0;i--) for(int j=0;j<26;j++) { if(s[i]=='a'+j) nxt[i][j]=i; //nearest position else nxt[i][j]=nxt[i+1][j]; // inherit the nearest next[i][j] } //dp, from the back to the front. //next[i][j]=x means that the index x is the nearest position from i,where s[x]=j-'a'. //precalculate next[i][j] then solve the problem in O(n) int cur=0,ans=1; for(int i=0;i<lent;i++){ int r=t[i]-'a'; if(nxt[0][r]>=lens){//next position is out of boundary (this character doesn't exist in s) flag=false; break; } if(nxt[cur][r]>=lens){ ans++; cur=0; } cur=nxt[cur][r]+1; } if(flag) cout<<ans<<'\n'; else cout<<"-1\n"; } return 0; }
再介绍一个O(nlogn)的暴力做法
只要知道upper_bound这个函数的用法就行了,vector里面存的是字母的位置,纯暴力即可,每次找到末尾就ans++。
具体看代码:
其中pos是字符k在vector里面的位置,ppos是当前已经查找到的s串的位置(类似于一个指针)。
#include<bits/stdc++.h> using namespace std; int main() { int q; cin>>q; while(q--) { string s,t; cin>>s>>t; vector<int>p[30]; for(int i=0; i<s.length(); i++) p[s[i]-'a'].push_back(i); int ans=1; bool flag=true; int pos,ppos=-1; for(int i=0; i<t.size(); i++) { int k=t[i]-'a'; if(p[k].size()==0) { flag=false; break; } pos=upper_bound(p[k].begin(),p[k].end(),ppos)-p[k].begin(); // cout<<pos<<endl; if(pos==p[k].size()) { ans++; pos=0; } ppos=p[k][pos]; } if(!flag) cout<<"-1\n"; else cout<<ans<<endl; } }
D.Same GCDs
https://codeforces.com/contest/1295/problem/D
题目大意:
已知方程gcd(a,m)=gcd(a+x,m),其中0<=x<m, a和m的规模1e10.
求满足该方程的x的个数。a和m由输入给定,输出x的个数。
证明都在代码注释里面了
其实不难 然而蒟蒻当时没开出来qwq
by the way 欧拉函数的定义是:小于或等于x的正整数中与x互质的数的数目,就是代码里面的phi(x)
#include<bits/stdc++.h> using namespace std; long long phi(long long x){ long long ans=x; for(long long i=2;i*i<=x;i++){ if(x%i==0){ ans=ans/i*(i-1); while(x%i==0) x=x/i; } } if(x>1) ans=ans/x*(x-1); return ans; } int main() { int t; cin>>t; while(t--){ long long a,m; cin>>a>>m; long long g=__gcd(a,m); cout<<phi(m/g)<<endl; } } /* Proof: gcd(a,m)=gcd(a+x,m),we need to find the number of appropriate x for this equation. Let gcd(a,m)=g,then gcd(a,m)=gcd(a+x,m)=gcd((a+x)mod m, m)=g. then the answer is sigma(0,m-1)[gcd(i,m)==g],where sigma(x,0,m-1)[gcd(a,m)==gcd((a+x)mod m , m)] = sigma(i,1,m)[gcd(i,m)==g] = sigma(i,1,m/g)[gcd(i/g,m/g)==1]...(*) According to the definition of Euler's function(phi(x)): (*) = phi(m/g). So the answer is phi(m/g), where g=gcd(a,m). */
EF在蒟蒻能力范围之外了,想了解这两题做法敬请移步dalao们的题解。
I wish you all have good luck and high ratings ( ´ ▽ ` )ノ

浙公网安备 33010602011771号