牛客 生日快乐
n<=10所以直接暴力切即可,对于每一刀,切的必须是x/n或者y/n的倍数,这样才能保证切n刀之后每块面积都相等,所以直接考虑每一刀对长切或者对宽切,对于每次的两种切法取最小值。假设对长切,那么就枚举从1到要切的块数除二的倍数i,该次切除的x就是i∗x/n,切出的另一块是x−i∗x/n,直到切到n=1为止,不需要再切了,计算长比宽,然后对这些块取最大值,然后考虑切宽的情况,和上面同理。切长和切宽之间取最小值即可(看的题解。。。https://blog.nowcoder.net/n/fe503123323d41598d8626f9a3817328?f=comment)
#include<iostream>
#include<cstring>
#include<algorithm>
#include<string>
#include<cstdio>
#include<iomanip>
#include<map>
#include<cmath>
#include<vector>
#include<queue>
#include<deque>
#include<list>
#include<stack>
#include<set>
#include<ctime>
#define ll long long
#define CHECK(x,y) (x>=0&&x<n&&y>=0&&y<n&&a[x][y]=='#')
//#include<bits/stdc++.h>
using namespace std;
const ll maxx=1e9;
int dir[4][3]={
{-1,0},
{1,0},
{0,-1},
{0,1},
};
int n;double X,Y;
double dfs(double x,double y,int t){
// cout<<"Yes"<<endl;
if(t==1) return max(x,y)/min(x,y);
double ans=1e9,h,w,a=x/t,b=y/t;//对于每一刀,切的必须是x/n或者y/n的倍数,这样才能保证切n刀之后每块面积都相等
for(int i=1;i<=t/2;i++){
h=max(dfs(i*a,y,i),dfs(x-i*a,y,t-i));
w=max(dfs(x,i*b,i),dfs(x,y-i*b,t-i));
ans=min(ans,min(h,w));
}
return ans;
}
int main(){
// freopen("in.txt","r",stdin);
cin>>X>>Y>>n;
printf("%.6f\n",dfs(X,Y,n));
return 0;
}
牛客 ZJH and Monkeys
这道题同样还是没有像出思路来,卡在了求点与点的距离上,看了题解知道了有一个方法求1到其他点的距离即可,而且求距离的方法也挺好Orz
大佬的思路:①:如果n是奇数的话,只能是偶+奇+偶 或 奇+偶+奇或者 奇,偶,偶 或者,偶奇奇
所以就是 ans=oushu*jishu*oushu*2;
ans+=jishu*oushu*jishu*2;
②:如果n是偶数的话,只能是偶偶奇,偶偶偶,奇奇奇, 奇奇偶
所以就是 ans+=(jishu*jishu+oushu*oushu)*n
因为 偶偶奇+偶偶偶=(偶偶)所有
所以我们就只需要找出根节点1到其他点的距离就好了,利用dfs求深度。
#include<iostream>
#include<cstring>
#include<algorithm>
#include<string>
#include<cstdio>
#include<iomanip>
#include<map>
#include<cmath>
#include<vector>
#include<queue>
#include<deque>
#include<list>
#include<stack>
#include<set>
#include<ctime>
#define ll long long
#define CHECK(x,y) (x>=0&&x<n&&y>=0&&y<n&&a[x][y]=='#')
//#include<bits/stdc++.h>
using namespace std;
const ll maxx=1e9;
int dir[4][3]={
{-1,0},
{1,0},
{0,-1},
{0,1},
};
int n,dis[100010];
ll ans,even,odd;
vector<int>a[100010];
void dfs(int u,int v,int cnt){//利用递归求距离——未曾设想的道路
dis[u]=cnt;
for(int i=0;i<a[u].size();i++){
int d=a[u][i];
if(d==v) continue;
dfs(d,u,cnt+1);
}
return;
}
int main(){
// freopen("in.txt","r",stdin);
int t;
cin>>t;
while(t--){
int u,v;
for(int i=0;i<=n;i++) a[i].clear();
cin>>n;
for(int i=1;i<n;i++){
cin>>u>>v;
a[u].push_back(v);
a[v].push_back(u);
}
dfs(1,1,1);
odd=0;even=0;
for(int i=1;i<=n;i++){
if(dis[i]%2==0)
even++;
else odd++;
}
ans=0;
if(n%2==1){
ans=even*odd*even*2;
ans+=odd*even*odd*2;
}
else{
ans+=(odd*odd+even*even)*n;
}
printf("%d\n",ans);
}
return 0;
}
牛客 轰炸区最优选取
能用前缀和做出来,原理还不是很懂,只知道这样做是对的。。。
#include<iostream>
#include<cstring>
#include<algorithm>
#include<string>
#include<cstdio>
#include<iomanip>
#include<map>
#include<cmath>
#include<vector>
#include<queue>
#include<deque>
#include<list>
#include<stack>
#include<set>
#include<ctime>
#define ll long long
#define CHECK(x,y) (x>=0&&x<n&&y>=0&&y<n&&a[x][y]=='#')
//#include<bits/stdc++.h>
using namespace std;
const ll maxx=1e9;
int dir[4][3]={
{-1,0},
{1,0},
{0,-1},
{0,1},
};
int n,k;
int a[55][55],ans=0;
/*void dfs(int x,int y,int orix,int oriy,int cnt){
if(x-orix+1==k&&y-oriy==k) {ans=max(ans,cnt);return;}
if(x-orix+1>k||y-oriy+1>k) return;
return dfs(x+1,y,orix,oriy,cnt+a[x+1][y]);
return dfs(x,y+1,orix,oriy,cnt+a[x][y+1]);
}*/
int main(){
// freopen("in.txt","r",stdin);
while(scanf("%d%d",&n,&k)!=EOF){
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
scanf("%d",&a[i][j]);
a[i][j]=a[i][j]+a[i-1][j]+a[i][j-1]-a[i-1][j-1];
}
}
ans=0;
for(int i=k;i<=n;i++){
for(int j=k;j<=n;j++){
ans=max(ans,a[i][j]-a[i-k][j]-a[i][j-k]+a[i-k][j-k]);
}
}
cout<<ans<<endl;
}
return 0;
}
还有一个笨方法,就是把所有的矩阵都求出来,我当时以为这样做会超时(会涉及四重循环)就没敢作,结果还真可以。。
#include<iostream>
#include<cstring>
#include<algorithm>
#include<string>
#include<cstdio>
#include<iomanip>
#include<map>
#include<cmath>
#include<vector>
#include<queue>
#include<deque>
#include<list>
#include<stack>
#include<set>
#include<ctime>
#define ll long long
#define CHECK(x,y) (x>=0&&x<n&&y>=0&&y<n&&a[x][y]=='#')
//#include<bits/stdc++.h>
using namespace std;
const ll maxx=1e9;
int dir[4][3]={
{-1,0},
{1,0},
{0,-1},
{0,1},
};
int n,k;
int a[55][55],ans=0;
void dfs(int x,int y,int orix,int oriy,int cnt){
if(x-orix+1==k&&y-oriy==k) {ans=max(ans,cnt);return;}
if(x-orix+1>k||y-oriy+1>k) return;
return dfs(x+1,y,orix,oriy,cnt+a[x+1][y]);
return dfs(x,y+1,orix,oriy,cnt+a[x][y+1]);
}
int main(){
// freopen("in.txt","r",stdin);
while(scanf("%d%d",&n,&k)!=EOF){
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
scanf("%d",&a[i][j]);
a[i][j]=a[i][j]+a[i-1][j]+a[i][j-1]-a[i-1][j-1];
}
}
ans=0;
for(int i=k;i<=n;i++){
for(int j=k;j<=n;j++){
ans=max(ans,a[i][j]-a[i-k][j]-a[i][j-k]+a[i-k][j-k]);
}
}
cout<<ans<<endl;
}
return 0;
}