Codeforces Round #607 (Div. 2)
A - Suffix Three
#include
using namespace std;
int main()
{
string s;
int t;
scanf("%d",&t);
while(t--)
{
cin>>s;
if(s[s.size()-2]=='p'&&s[s.size()-1]=='o')
cout<<"FILIPINO"<
B - Azamon Web Services
O(n^3)的做法加上小剪枝(stl的cmp有多快我不知道)
#include
using namespace std;
int T;
string s,t;
int main()
{
cin>>T;
while(T--)
{
cin>>s>>t;
if(st[i]) continue;
swap(s[i],s[j]);
if(s
C - Cut and Paste
题目转弯瞎说一大堆,其实就是把后面的一段复制来复制去,那么直接模拟即可
如果字符串的长度大于x了只有计数,否则在计数的同时把字符串加长。
#include
using namespace std;
typedef long long ll;
const int mod=1e9+7;
string s;
int main()
{
int t;cin>>t;
while(t--)
{
int x;
cin>>x>>s;
ll len=s.size(),bk=s.size();
bool flag=false;
for(int i=0;i=s.size()) break;
if(!flag)
{
if(bk>0) bk--;
string k=s.substr(i+1,bk);
if(s[i]-'0'==2) s+=k;
if(s[i]-'0'==3) s+=k+k;
len=(len+bk*(s[i]-'0'-1))%mod;
bk=bk*(s[i]-'0')%mod;
if(len>x) flag=true;
}
else
{
if(bk>0) bk--;
len=(len+bk*(s[i]-'0'-1))%mod;
bk=bk*(s[i]-'0')%mod;
}
}
printf("%lld\n",len);
}
}
D - Beingawesomeism
答案只有0~4和无解几种可能,分类讨论:
无解:矩阵全为P
0次:矩阵全为A
1次:矩阵在边界一行或者一列全为A
2次:矩阵在四个顶点有一个A或者有某行某列全为A
3次:矩阵在边界有一个A
4次:矩阵中有A即可
#include
using namespace std;
const int N=77;
int n,m;
char s[N][N];
bool judge1()
{
bool f1=true,f2=true,f3=true,f4=true;
for(int i=1;i<=m;i++)
{
if(s[1][i]!='A') f1=false;
if(s[n][i]!='A') f2=false;
}
for(int i=1;i<=n;i++)
{
if(s[i][1]!='A') f3=false;
if(s[i][m]!='A') f4=false;
}
return f1|f2|f3|f4;
}
bool judge2()
{
if(s[1][1]=='A'||s[1][m]=='A'||s[n][1]=='A'||s[n][m]=='A') return true;
for(int i=1;i<=n;i++)
{
bool flag=true;
for(int j=1;j<=m;j++)
if(s[i][j]!='A') {flag=false;break;}
if(flag) return true;
}
for(int j=1;j<=m;j++)
{
bool flag=true;
for(int i=1;i<=n;i++)
if(s[i][j]!='A'){flag=false;break;}
if(flag) return true;
}
return false;
}
bool judge3()
{
for(int i=1;i<=m;i++)
{
if(s[1][i]=='A') return true;
if(s[n][i]=='A') return true;
}
for(int i=1;i<=n;i++)
{
if(s[i][1]=='A') return true;
if(s[i][m]=='A') return true;
}
return false;
}
int main()
{
int t;scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%s",s[i]+1);
int tot=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
if(s[i][j]=='P') tot++;
if(tot==n*m) printf("MORTAL\n");
else if(tot==0) printf("0\n");
else if(judge1()) printf("1\n");
else if(judge2()) printf("2\n");
else if(judge3()) printf("3\n");
else printf("4\n");;
}
}
E - Jeremy Bearimy
从边的角度考虑,如果要使总和尽可能的大,就是要使得边被路径穿过的次数最大那么一条连接u,v边被选的次数就使max(si[u],si[v]),贡献的价值是max(si[u],si[v])*wi
再考虑小的,如果一条边两边的点数都为偶数,那么只有使边两边相互配对即可,这条边就不需要被选,而除此之外的边只能被迫选择,如果采用的方案足够优秀,是不会有边重合的,因此一次dfs即可。
#include
using namespace std;
typedef long long ll;
const int N=2e5+5;
ll ans,res;
int k,tot,head[N],si[N],nex[N<<1],to[N<<1],wi[N<<1];
void add(int u,int v,int w){to[++tot]=v;nex[tot]=head[u];head[u]=tot;wi[tot]=w;}
void dfs(int u,int p)
{
si[u]=1;
for(int i=head[u];i;i=nex[i])
{
int v=to[i];if(v==p) continue;
dfs(v,u);
si[u]+=si[v];
ans+=(ll)min(si[v],k-si[v])*wi[i];
if(si[v]%2==0&&(k-si[v])%2==0) res-=wi[i];
}
}
int main()
{
int t;scanf("%d",&t);
while(t--)
{
memset(head,0,sizeof(head));tot=0;
scanf("%d",&k);
k*=2;
ans=res=0;
for(int i=1;i
Codeforces Round #608 (Div. 2)
A - Suits
#include
using namespace std;
typedef long long ll;
int main()
{
ll a,b,c,d,e,f;
scanf("%lld%lld%lld%lld%lld%lld",&a,&b,&c,&d,&e,&f);
int t=min(a,d);
ll ans=0;
for(int i=0;i<=t;i++)
ans=max(ans,i*e+min(min(b,c),d-i)*f);
cout<
B - Blocks
无论怎么翻,两种颜色的奇偶性不变,因此线性的从左到右翻过去
#include
using namespace std;
int n;
string s;
int main()
{
cin>>n>>s;
int ans1=0,ans2=0;
for(int i=0;iq;
for(int i=0;i
C - Shawarma Tent
对于一个点x,y,假设路径是sx,sy->sx,y->x,y,那么如果有另外一个点,如果走另外一个点不经过sx,sy->sx,y这条路,那么第二条路不会重合,反正很容易想到只要往sx,sy的上下左右四个方向加点就行
By Huah, contest: Codeforces Round #608 (Div. 2), problem: (C) Shawarma Tent, Accepted, #
#include
using namespace std;
const int N=2e5+5;
int n,sx,sy;
struct node
{
int x,y;
}a[N];
int ans1,ans2,ans3,ans4;
int main()
{
scanf("%d%d%d",&n,&sx,&sy);
for(int i=1;i<=n;i++)
{
scanf("%d%d",&a[i].x,&a[i].y);
int x=a[i].x-sx,y=a[i].y-sy;
if(y>0) ans1++;
if(y<0) ans2++;
if(x>0) ans3++;
if(x<0) ans4++;
}
if(ans1>=ans2&&ans1>=ans3&&ans1>=ans4)
printf("%d\n%d %d\n",ans1,sx,sy+1);
else if(ans2>=ans1&&ans2>=ans3&&ans2>=ans4)
printf("%d\n%d %d\n",ans2,sx,sy-1);
else if(ans3>=ans1&&ans3>=ans2&&ans3>=ans4)
printf("%d\n%d %d\n",ans3,sx+1,sy);
else printf("%d\n%d %d\n",ans4,sx-1,sy);
}
D - Portals
首先倒推一个数组d[i],表示要想从这里跑到终点,那么至少要有d[i]的军力。然后想一想,如果在第i个港口,它在i+1~n的位置的时候也可以保护它,那么可以先不管它,到后面再保护也是一样的。那么就线性的去模拟,开一个优先队列,如果碰到一个在i位置可以保护,跑到后面就不能保护了,那么我只能选择保护这个港口了,当然和优先队列里面的比较,因为优先队列里的元素都是已经被保护的,但想一下,放弃前面一个小价值的城堡,保护后面一个价值更大的城堡,这样也是可以滴。
#include
using namespace std;
typedef long long ll;
const int N=5005;
int n,m,k,a[N],b[N],c[N],d[N];
vectorv[N];
bool vis[N];
int vv[N];
struct node
{
int x,id;
node(int x=0,int id=0):x(x),id(id){}
bool operator<(const node&o)const
{
return x>o.x;
}
};
priority_queueq;
pairp[N];
int main()
{
scanf("%d%d%d",&n,&m,&k);
for(int i=1;i<=n;i++)
scanf("%d%d%d",&a[i],&b[i],&c[i]);
for(int i=1;i<=m;i++)
{
int x,y;scanf("%d%d",&x,&y);
v[x].push_back(y);
vv[y]++;
}
for(int i=1;i<=n;i++) vv[i]++;
d[n]=a[n];
for(int i=n-1;i>=1;i--)
d[i]=max(a[i],d[i+1]-b[i]);
if(k=0;j--)
if(!vis[p[j].second])
{
if(now>d[i+1])
{
now--;
q.push(node(p[j].first,p[j].second));
vis[p[j].second]=true;
}
else if(!q.empty())
{
if(q.top().x
E Common Number
根据题意可以画出如图左边的一颗树,一个数的出现次数即为该结点以及该结点所有儿子结点的数量。
但是如图左边的树是不容易计算的,我们把数变一下形,转换成如图右边的二叉树,由于计算结点时出现多次的结点也只有一次的贡献
所以问题转换为在二叉树上进行计算,当要计算的数为x,如果x为奇数,就是普通二叉树上计算结点,如果x为偶数,显然计算的是x/2的结点数量减1。
#include
using namespace std;
typedef long long ll;
ll n,k;
ll cal(ll x)
{
ll tot=1,ans=0;
while(x*2<=n)
{
ans+=tot;
x*=2;tot*=2;
}
ans+=min(tot,n-x+1);
return ans;
}
int main()
{
scanf("%lld%lld",&n,&k);
ll l=1,r=n/2,ans=1;
while(l<=r)
{
ll m=l+r>>1;
if(cal(m)-1>=k) ans=max(ans,m*2),l=m+1;
else r=m-1;
}
l=0,r=(n-1)/2;
while(l<=r)
{
ll m=l+r>>1;
if(cal(m*2+1)>=k) ans=max(ans,m*2+1),l=m+1;
else r=m-1;
}
printf("%lld\n",ans);
}