比赛链接:EC Final 2020
和 @cyx20110930 组的队,用他的号交的题。顺便帮助他橙名,好耶!(rk 25,我俩各写 2 道)
Problem B:
这道是 @cyx20110930 写的,顺便安利(copy)一下他的题解。
题目意思
有一个的棋盘,操作次,每次删掉一个方格,问还剩几个长方形。
思路
正难则反,既然数有多少个比较困难,就直接每次查找少了几个长方形,十分简单。
代码
//暴力
//TEAM_NAME:CYX&LSY AK ICPC
//Problem B
//By CYX
#include<bits/stdc++.h>
using namespace std;
#define int long long
int n,m,down[505][505],up[505][505],grid[505][505];
int main()
{
cin>>n>>m;
//预处理
for(int i=1;i<=n;i++) {
for(int j=1;j<=m;j++){
up[i][j]=0;
down[i][j]=n+1;
}
}
int ans=n*(n+1)/2*m*(m+1)/2,q=n*m;
while(q--){
int x,y;
cin>>x>>y;
int u=0,d=n+1;
for(int j=y;j>=1;j--){//从1至y找u,d,看对每个格子能影响多大区域
if(grid[x][j]) break;
u=max(u,up[x][j]+1);
d=min(d,down[x][j]-1);
int a=u,b=d;
for(int k=y;k<=m;k++){//从y至n找u,d,看对每个格子能影响多大区域
if(grid[x][k]) break;
a=max(a,up[x][k]+1);
b=min(b,down[x][k]-1);
ans-=abs(x-a+1)*abs(b-x+1);
}
}
cout<<ans<<endl;
//更新
grid[x][y]=1;
for(int j=x;j<=n;j++)up[j][y]=max(up[j][y],x);
for(int j=x;j>=1;j--)down[j][y]=min(down[j][y],x);
}
return 0;
}
Problem F:
这题是我写的awa。
题目意思
有一个无限大的象棋棋盘,两个玩家分别有个车,放置在上。
两个车可以被相互攻击要满足这三个条件:
①属于不同的玩家
②有相同的x或者y
③中间没有其他棋子
输出有哪些车可以被攻击到。
思路
我们直接用一个 map 来保存相同行和相同列的棋子,这里我们可以把车按照不同的玩家分为。然后我们遍历同一行/列的棋子,看看是否属于不同的玩家。
代码
//模拟
//TEAM_NAME:CYX&LSY AK ICPC
//Problem F
//By LSY
#include <bits/stdc++.h>
using namespace std;
struct rook{
int pos;
int id;
};
map<int,vector<rook>> row;
map<int,vector<rook>> col;
bool ans[400005];
bool cmp(rook x,rook y){
return x.pos<y.pos;
}
int main(){
int n1,n2;
cin>>n1>>n2;
for(int i=1;i<=n1;i++){
int a,b;
cin>>a>>b;
row[a].push_back({b,i});
col[b].push_back({a,i});
}
for(int i=1;i<=n2;i++){
int a,b;
cin>>a>>b;
row[a].push_back({b,i+n1});
col[b].push_back({a,i+n1});
}
for(auto p:row){
auto c=p.second;
sort(c.begin(),c.end(),cmp);
for(int i=1;i<c.size();i++){
if((c[i].id<=n1 && c[i-1].id>n1) || (c[i-1].id<=n1 && c[i].id>n1)){
ans[c[i].id]=1;
ans[c[i-1].id]=1;
}
}
}
for(auto q:col){
auto r=q.second;
sort(r.begin(),r.end(),cmp);
for(int i=1;i<r.size();i++){
if((r[i].id<=n1 && r[i-1].id>n1) || (r[i-1].id<=n1 && r[i].id>n1)){
ans[r[i].id]=1;
ans[r[i-1].id]=1;
}
}
}
for(int i=1;i<=n1;i++)
cout<<ans[i];
cout<<endl;
for(int i=n1+1;i<=n1+n2;i++)
cout<<ans[i];
return 0;
}
Problem K:
继续copy @cyx20110930 的题解。
题目意思
每人 2 张牌,公共牌区 5 张牌,现在给你你的牌,与公共牌区的 3 张牌,问你是否保证胜利。
思路
只有同花顺可能 Allin。(保证胜利)
证明:
题目给定的牌为 h1,h2,c1,c2,c3 设对方的两张为 g1,g2 剩下两张未给出的公共牌为 c4,c5。
若给定的五张牌次于四张一样(炸弹)的牌型,则存在 g1=g2=c4=c5 使得对方构成炸弹的牌型,故不可 Allin。
若给定的五张牌构成炸弹的牌型,此时由于四种花色都有,则一定有一张公共牌的花色不同于 h1 与 h2,不妨设这张牌为 c1,那么存在一种方案使得 c1,c4,c5,g1,g2 构成同花顺,故不可 Allin。
当给定的五张牌为同花顺,此时可枚举对方牌型,看是否有赢的可能。对方赢的牌型必须满足以下条件:
-
是大于给定五张牌的同花顺
-
没有 h1,h2
-
至少包含 c1,c2,c3 其中一张
综上,证毕。
代码
当时他口胡出了上面的思路,丢给我写的。(CYX op)
//模拟
//TEAM_NAME:CYX&LSY AK ICPC
//Problem K
//By LSY
#include <bits/stdc++.h>
using namespace std;
string h1,h2,c1,c2,c3;
vector<int> v;
int transfer(string x){
if(x[0]>='0' && x[0]<='9')
return x[0]-'0';
if(x[0]=='T')
return 10;
if(x[0]=='J')
return 11;
if(x[0]=='Q')
return 12;
if(x[0]=='K')
return 13;
if(x[0]=='A')
return 14;
}
int main(){
int T;
cin>>T;
while(T--){
v.clear();
string h1,h2,c1,c2,c3;
cin>>h1>>h2>>c1>>c2>>c3;
int flag=0,p=0;
if(h1[1]==h2[1] && h2[1]==c1[1] && c2[1] == c1[1] && c3[1] == c2[1]){
v.push_back(transfer(h1));
v.push_back(transfer(h2));
v.push_back(transfer(c1));
v.push_back(transfer(c2));
v.push_back(transfer(c3));
sort(v.begin(),v.end());
for(int i=1;i<v.size();i++){
if(v[i-1]+1==v[i])
continue;
else{
p=1;
break;
}
}
if(!p){
if(max(transfer(h1),transfer(h2))>=10)
flag=1;
if(max(transfer(h1),transfer(h2))>=max(max(transfer(c1),transfer(c2)),transfer(c3)))
flag=1;
}
}
if(flag){
cout<<"Allin"<<endl;
continue;
}
v.clear();
if(transfer(h1)==14 && transfer(h2)==5){
if(h1[1]==h2[1] && h2[1]==c1[1] && c2[1]==c1[1] && c3[1]==c2[1]){
v.push_back(transfer(c1));
v.push_back(transfer(c2));
v.push_back(transfer(c3));
sort(v.begin(),v.end());
if(v[0]==2 && v[1]==3 && v[2]==4){
cout<<"Allin"<<endl;
continue;
}
}
}
if(transfer(h2)==14 && transfer(h1)==5){
if(h1[1]==h2[1] && h2[1]==c1[1] && c2[1]==c1[1] && c3[1]==c2[1]){
v.push_back(transfer(c1));
v.push_back(transfer(c2));
v.push_back(transfer(c3));
sort(v.begin(),v.end());
if(v[0]==2 && v[1]==3 && v[2]==4){
cout<<"Allin"<<endl;
continue;
}
}
}
cout<<"check"<<endl;
}
return 0;
}
Problem L:
依旧是搬运 @cyx20110930 的题解。
题目意思
有一个数组,求出乘积最小的 t 数组使得对于每个 是完全平方数。
思路
明显对于每个其因数的出现次数只有两种情况:都是奇数或都是偶数。
对这两种情况分别计算,取最小值即可。
代码
//签到
//TEAM_NAME:CYX&LSY AK ICPC
//Problem B
//By CYX
#include<bits/stdc++.h>
using namespace std;
#define int long long
int n;
bool isprime[1000005];
int pri[1000005],s[1000005],vis[1000005],num[1000005],prime[1000005],cnt,tot;
void init(){
s[1]=1;
for(int i=2;i<=1000005;i++){
if(!isprime[i])prime[++cnt]=i,s[i]=i;
for(int j=1;j<=cnt;j++){
if(i*prime[j]>1000005)break;
isprime[i*prime[j]]=1;
s[i*prime[j]]=prime[j];
if(!(i%prime[j]))break;
}
}
}
int qpow(int a,int b){
int ans=1;
while(b){
if(b&1)ans=ans*a%1000000007;
a=a*a%1000000007;
b>>=1;
}
return ans;
}
int main(){
init();
cin>>n;
for(int i=1;i<=n;i++){
int x;cin>>x;
tot=0;
while(x>1){
if(!vis[s[x]])pri[++tot]=s[x];
vis[s[x]]++;
x/=s[x];
}
for(int j=1;j<=tot;j++){
if(vis[pri[j]]%2==1)num[pri[j]]++;
//num是指数为奇数的质因子的出现次数
vis[pri[j]]=0;
}
}
int ans=1;
for(int i=1;i<=cnt;i++){
if(!num[prime[i]])continue;
ans*=qpow(prime[i],min(num[prime[i]],n-num[prime[i]]));
ans%=1000000007;
}
cout<<ans;
return 0;
}
友情提醒:不要Ctrl C+Ctrl V