AtCoder Beginner Contest 246
AtCoder Beginner Contest 246
D
题意
求一个\(x\geq n\) 使得\(x=a^3+a^2b+ab^2+b^3\)且\(n\leq10^{18}\)
思路
变形 \(x=(a+b)(a^2+b^2)\) ,那么a、b的范围在1e6
从大到小枚举每个a,那么每个符合情况的b的最小值一定单调不升
代码
int f(int x,int y)
{
return (x+y)*(x*x+y*y);
}
void solve()
{
// (a+b)(a^2+b^2)
//双指针
cin>>n;
m=1e6;
int r=1e6;
for(int i=0;i<=m;i++)
{
int k;
while(1)
{
k=f(i,r);
if(k>=n&&r>=0) ans=min(ans,k),r--;
else break;
}
}
cout<<ans<<endl;
}
E
思路
以为是简单的bfs,一直wa,明明都过了52个点了,后来看题解发现不对劲啊,一个点可能从两个方向走过来而且它们的步数是相等的。所以vis数组要开多一维
upd:2023/4/15 遇到了一题差不多的
代码
bool vis[N][N][2];
void bfs()
{
queue<node> q;
memset(dis,-1,sizeof(dis));
q.push({sx,sy});
dis[sx][sy]=0;
while(q.size())
{
node tmp=q.front();
q.pop();
int x=tmp.x,y=tmp.y;
for(int i=0;i<4;i++)
{
int nx=x,ny=y;
while(1)
{
nx+=dx[i],ny+=dy[i];
if(!check(nx,ny)||s[nx][ny]=='#') break;
if(vis[nx][ny][i&1]) break;
vis[nx][ny][i&1]=1;
if(dis[nx][ny]==-1)
{
dis[nx][ny]=dis[x][y]+1;
q.push({nx,ny});
}
}
}
}
cout<<dis[tx][ty]<<"\n";
}
void solve()
{
cin>>n;
cin>>sx>>sy>>tx>>ty;
for(int i=0;i<n;i++) cin>>s[i];
sx--,sy--,tx--,ty--;
if((sx+sy)%2!=(tx+ty)%2) {cout<<"-1\n";return;}
bfs();
}
F
题意
给出n个字符串,操作:选定一个字符串,选择其中的字符(可重复选择)构成一个长度为k的字符串,问有多少种可能的结果
思路
假设每个字符串可以产生的长度为m的字符串集合为s[i]
则总个数是所有集合取并集,由容斥原理可知,集合总数=所有集合的总和+奇数个集合的交集-偶数个集合的交集
一个字符串所含有的不同字符的个数为c,则可构成的字符串个数为\(c^k\)
取交集:n个字符串交集中的字符串的字符是这n个字符串都有的,假设交集的字符串不同字符个数为c,则共有\(c^k\)个
代码
void solve()
{
cin>>n>>m;
for(int i=0;i<n;i++)
{
string s;
cin>>s;
for(int j=0;j<s.size();j++) ch[i][s[j]-'a']=1;
}
int ans=0;
for(int i=1;i<(1<<n);i++)
{
int res=0,cnt=0;
for(int j=0;j<26;j++) tmp[j]=0;
for(int j=0;j<n;j++)
{
if((i>>j)&1)
{
cnt++;
for(int k=0;k<26;k++) tmp[k]+=ch[j][k];
}
}
for(int j=0;j<26;j++) if(tmp[j]==cnt) res++;
if(cnt&1) ans=(ans+q_pow(res,m)%mod)%mod;
else ans=(ans-q_pow(res,m)+mod)%mod;
}
cout<<ans<<endl;
}