AtCoder Regular Contest 108
A - Sum and Product
思路:
联立方程,得到二次函数,易知函数具有单调性, n \sqrt{n} n枚举
#include <iostream>
using namespace std;
typedef long long ll;
ll p,s;
int main(){
cin>>s>>p;
int ok=0;
for(ll i=1;s-i>=1;i++){
if(s*i-i*i==p){
ok=1;
break;
}else if(s*i-i*i>p){
break;
}
}
if(ok) cout<<"Yes\n";
else cout<<"No\n";
}
Abbreviate Fox
思路:
模拟:
可以看出直接模拟删除 f o x fox fox就行。
栈:
可以用栈将失配压入栈内,当一个 f o x fox fox配对成功删除,就出栈上次代配对的,具体操作看代码,时间复杂度 O ( n ) O(n) O(n)。
#include <iostream>
#include <vector>
using namespace std;
const int N=3e5+7;
int n;
char a[N];
vector <int> sa;
int main(){
cin>>n;
cin>>(a+1);
int ok=0,ans=0;
for(int i=1;i<=n;i++){
if(ok==1&&a[i]=='o'){
ok=2;
}else if(ok==2&&a[i]=='x'){
ans++;
if(!sa.empty()){
ok=sa.back();
sa.pop_back();
}else{
ok=0;
}
}else{
if(a[i]=='f'){
sa.push_back(ok);
ok=1;
}else{
sa.push_back(ok);
ok=0;
}
}
}
cout<<n-3*ans<<"\n";
}
C - Keep Graph Connected
思路:
结论:
因为可以删边成棵树
那么图连通,那么一定有解,那么其结构将会是棵树。
贪心:
1.如果上个节点已占有边,那么当前节点优先选能占有下个节点的边且合法的值。
2.如果上个节点未占有边,那么当前节点只能选边的值。
#include <iostream>
using namespace std;
const int N=2e5+7;
struct node{int to,w,next;}e[N*2];
int n,m,vis[N],ans[N];
int head[N],tot;
void add(int u,int v,int w){
e[++tot].to=v;
e[tot].w=w;
e[tot].next=head[u];
head[u]=tot;
}
void dfs(int p,int fa,int pre,int ok){
vis[p]=1;
int col=0;
if(ok){
for(int i=head[p];i;i=e[i].next){
if(vis[e[i].to]) continue;
int w=e[i].w;
if(w!=ans[fa]&&w!=pre){
col=w;
break;
}
}
if(!col){
for(int i=1;i<=n;i++){
if(i!=ans[fa]&&i!=pre){
col=i;
break;
}
}
}
ans[p]=col;
for(int i=head[p];i;i=e[i].next){
int v=e[i].to,w=e[i].w;
if(vis[v]) continue;
dfs(v,p,w,col==w);
}
}else{
ans[p]=pre;
for(int i=head[p];i;i=e[i].next){
int v=e[i].to,w=e[i].w;
if(vis[v]) continue;
dfs(v,p,w,pre==w);
}
}
}
int check(){
for(int i=1;i<=n;i++){
if(!vis[i]) return 0;
}
return 1;
}
int main(){
cin>>n>>m;
for(int i=1;i<=m;i++){
int u,v,w;
cin>>u>>v>>w;
add(u,v,w),add(v,u,w);
}
for(int i=1;i<=n;i++){
dfs(i,0,0,1);
break;
}
if(check()){
for(int i=1;i<=n;i++) cout<<ans[i]<<"\n";
}else{
cout<<"No\n";
}
}
D - AB
思路:
大讨论:
如果 C A A = A , C A B = A C_{AA}=A,C_{AB}=A CAA=A,CAB=A。显然答案是1
如果 C A B = B , C B B = B C_{AB}=B,C_{BB}=B CAB=B,CBB=B。显然答案是1
如果 C A B = A , C A A = B , C B A = B C_{AB}=A,C_{AA}=B,C_{BA}=B CAB=A,CAA=B,CBA=B,或 C A B = B , C B B = A , C B A = A C_{AB}=B,C_{BB}=A,C_{BA}=A CAB=B,CBB=A,CBA=A。
- 其 A _ _ A B A\_\_AB A__AB中间将插的是任意组合,即答案为 2 n − 3 2^{n-3} 2n−3
如果 C A B = A , C A A = B , C B A = A C_{AB}=A,C_{AA}=B,C_{BA}=A CAB=A,CAA=B,CBA=A,或 C A B = B , C B B = A , C B A = B C_{AB}=B,C_{BB}=A,C_{BA}=B CAB=B,CBB=A,CBA=B。
- 将是构成类是为不含连续0的01序列的个数,即答案为fib[n-1]。
#include <iostream>
using namespace std;
typedef long long ll;
const int N=1007;
const ll mod=1e9+7;
int n;
ll fib[N];
char c1,c2,c3,c4;
ll ksm(ll x,ll p){
ll res=1;
while(p){
if(p&1) res=res*x%mod;
p/=2;
x=x*x%mod;
}
return res;
}
void init(){
fib[1]=1,fib[2]=1;
for(int i=3;i<=n;i++){
fib[i]=(fib[i-1]+fib[i-2])%mod;
}
}
int main(){
cin>>n;
cin>>c1>>c2>>c3>>c4;
if(n==2){
cout<<1<<"\n";
return 0;
}
init();
if((c2=='A'&&c1=='A')||(c2=='B'&&c4=='B')){
cout<<"1\n";
}else if(c2=='A'&&c1=='B'&&c3=='B'){
cout<<ksm(2,n-3)<<"\n";
}else if(c2=='B'&&c4=='A'&&c3=='A'){
cout<<ksm(2,n-3)<<"\n";
}else{
cout<<fib[n-1]<<"\n";
}
}