日常的机房模拟.....
又去听数理化了
然后只考了一个小时出头
然后260......
最后40分没拿到是因为要写高精度..................
T1
我们可以很淡定的推一推规律
我们只需要象征性的推一下规律就知道这道题的规律非常非常的显然
我们记录下一个矩阵的横行的前缀和,并且记录下另一个矩阵的竖行的前缀和
然后每一次计算x1,y1,x2,y2的时候把前一个矩阵1~n的x1~x2的前缀和乘y1~y2的前缀和,全部相加就出来了
但是它的定点很坑人........并没有告诉你端点......所以要特判以后swap
考场上11mins搞定........
贴上丑陋的代码.......
#include<cstdio>
#include<algorithm>
#define OP "matrix"
#define LL long long
const int MAXN=2005;
int G1[MAXN][MAXN];
int G2[MAXN][MAXN];
LL sum1[MAXN][MAXN];//第一个矩阵中的列前缀和
LL sum2[MAXN][MAXN];//第二个矩阵中的行前缀和
int main()
{
std::freopen(OP".in","r",stdin);
std::freopen(OP".out","w",stdout);
int n,m;
std::scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
std::scanf("%d",G1[i]+j);
sum1[i][j]=sum1[i-1][j]+1ll*G1[i][j];//第j列前i个
}
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
std::scanf("%d",G2[i]+j);
sum2[i][j]=sum2[i][j-1]+1ll*G2[i][j];//第i行前j个
}
}
while(m--)
{
int a,b,c,d;
std::scanf("%d%d%d%d",&a,&b,&c,&d);
if(b>d)
{
std::swap(b,d);
}
if(a>c)
{
std::swap(a,c);
}
LL ans=0;
for(int i=1;i<=n;i++)//枚举列数
{
ans+=1ll*(1ll*sum1[c][i]-sum1[a-1][i])*1ll*(sum2[i][d]-sum2[i][b-1]);
}
std::printf("%lld\n",ans);
}
return 0;
}
/*
3 2
1 9 8
3 2 0
1 8 3
9 8 4
0 5 15
1 9 6
1 1 3 3
2 3 1 2
*/
T2
洛谷黄题
稍微脑洞一下就知道最优的点在给出的点之间
n^3*log(n)枚举(log是排序)一下
15mins过
#include<cstring>
#include<cstdio>
#include<algorithm>
#define OP "tower"
#define LL long long
const int MAXN=55;
int x[MAXN],y[MAXN];
LL dis[MAXN],ans[MAXN];
int main()
{
std::freopen(OP".in","r",stdin);
std::freopen(OP".out","w",stdout);
int n;
std::scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d%d",x+i,y+i);
}
std::memset(ans,0x7f,sizeof(ans));
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
for(int k=1;k<=n;k++)
{
dis[k]=abs(x[k]-x[i])+abs(y[k]-y[j]);
}
std::sort(dis+1,dis+1+n);
LL sum=0;
for(int k=1;k<=n;k++)
{
sum+=1ll*dis[k];
ans[k]=std::min(ans[k],sum);
}
}
}
for(int i=1;i<=n;i++)
{
std::printf("%lld\n",ans[i]);
}
return 0;
}
T3
本来也是树形dp的水水题
设dp[u][0]为以u为根的子树里不选u的最大匹配
dp[u][1]为u为根子树里选u的最大匹配
g[u][0/1]为对应情况的方案数
所以
dp[u][1]=(求和符号sigma__用不来markdown好悲伤)(max(dp[v][1],dp[u][0]+dp[v][0]+1))
dp[u][0]=sigma(max(dp[v][0],dp[v][1]))
对于g[u][0],如果某个dp[v][0]!=dp[v][1],那么就把g[u][0]*=g[v][1],否则就是g[u][0]*=g[v][1]+g[v][0]
g[u][1]基本同理
随便水水就过去了.........
奈何要写高精度
考场上没时间了60分算法苟了上去
然后格式错了1分没有......
然后现在高精度还没有调出来.........
贴上60pts的代码....
把g数组改成高精度就能够AC
#include<cstdio>
#include<cstring>
#include<algorithm>
#define OP "tree"
#define LL long long
const int MAXN=1e3+5;
LL g[MAXN][MAXN];
class Edge
{
public:
int nxt;
int to;
}edge[MAXN<<1];
int head[MAXN];
int cnt;
void add(int from,int to)
{
edge[++cnt].nxt=head[from];
edge[cnt].to=to;
head[from]=cnt;
}
LL dp[MAXN][2];
int fat[MAXN];
int root;
void dfs(int u)
{
g[u][0]=1;
g[u][1]=1;
for(int i=head[u];i;i=edge[i].nxt)
{
int v=edge[i].to;
if(v==fat[u])
{
continue;
}
dfs(v);
if (dp[u][1])
{
dp[u][1]+=dp[v][1];
if(dp[v][0]^dp[v][1])
{
g[u][1]*=g[v][1];
}
else g[u][1]*=1ll*g[v][0]+g[v][1];
}
int t=dp[u][0]+dp[v][0]+1;
if(t>dp[u][1])
{
dp[u][1]=t;
g[u][1]=1ll*g[u][0]*g[v][0];
}
else
if (t==dp[u][1])
{
g[u][1]+=g[u][0]*g[v][0];
}
dp[u][0]+=dp[v][1];
if(dp[v][0]^dp[v][1])
{
g[u][0]*=g[v][1];
}
else
{
g[u][0]*=g[v][0]+g[v][1];
}
}
if (!dp[u][1])
{
g[u][1]=0;
}
}
int main()
{
//std::freopen(OP".in","r",stdin);
//std::freopen(OP".out","w",stdout);
int n;
std::scanf("%d",&n);
for(int i=n;i;i--)
{
int f,m;
std::scanf("%d%d",&f,&m);
for(int i=1;i<=m;i++)
{
int u;
std::scanf("%d",&u);
fat[u]=f;
add(f,u);
add(u,f);
}
}
for(int i=1;i<=n;i++)
{
if(!fat[i])
{
root=i;
}
}
dfs(root);
std::printf("%lld\n",dp[1][1]);
if(dp[1][1]^dp[1][0])
{
std::printf("lld\n",g[1][1]);
}
else
{
std::printf("%lld\n",g[1][1]+g[1][0]);
}
return 0;
}
/*
7
1 3 2 4 7
2 1 3
4 1 6
3 0
7 1 5
5 0
6 0
*/