【A. Patrick and Shopping】
【题目大意】有三个点,给出两点之间的距离,求从A出发访问BC后返回A的最短路径。
【分析】乱搞即可……对于我这种蒟蒻写出所有的情况最粗暴,第一次还没考虑全……
代码:
#include <cstdio>
#include <algorithm>
using namespace std;
int main()
{
int d1,d2,d3;
scanf("%d%d%d",&d1,&d2,&d3);
int ans1=d1+d1+d2+d2;
int ans2=d1+d2+d3;
int ans3=d1+d1+d3+d3;
int ans4=d2+d2+d3+d3;
printf("%d\n",min(min(ans1,ans2),min(ans3,ans4)));
}
【B. Spongebob and Joke】
【题目大意】输入数列f与数列a,求数列a(i)使得b(i) = f(a(i)),若不存在输出Impossible,若多解输出Ambiguity。
【分析】开个Map模拟一下好了……神TM最后一分钟给人叉了,神TM最后两秒改对交了……虽然没卵用还是没多少分……
代码:
#include <cstdio>
#include <algorithm>
#include <map>
using namespace std;
map<int,int> mm;
int a[100100],b[100100],f[100100],cnt[100100];
int main()
{
int n,m,Ambiguity=0;
scanf("%d%d",&n,&m);
for (int i=1; i<=n; i++) { scanf("%d",&f[i]); mm[f[i]]=i; cnt[f[i]]++; }
for (int i=1; i<=m; i++) scanf("%d",&b[i]);
for (int i=1; i<=m; i++)
{
if(mm.find(b[i])==mm.end()) { puts("Impossible"); return 0; }
int x=mm[b[i]];
if (cnt[b[i]]>1) Ambiguity=1;
a[i]=x;
}
if (Ambiguity) { puts("Ambiguity"); return 0; }
puts("Possible");
for (int i=1; i<=m; i++) printf("%d ",a[i]);
}
【C. Day at the Beach】
【题目大意】有一列数,分成若干块分别排序,求最多能分成多少块,使得排序后整个数列有序。
【分析】模拟一下,从最小的数到最大的数依次考虑,当前块必须把当前最小的数包含进去,可以分块就分。
代码:
#include <cstdio>
#include <algorithm>
using namespace std;
struct node { int v,id,tag; } a[100010];
int cmp1(node x, node y) { return x.v<y.v; }
int cmp2(node x, node y) { return x.id<y.id; }
int ccount[100010];
int main()
{
int n,tt;
scanf("%d",&n);
for (int i=1; i<=n; i++) scanf("%d",&a[i].v),a[i].id=i;
sort(a+1,a+n+1,cmp1);
a[1].tag=tt=1; ccount[tt]=1;
for (int i=2; i<=n; i++)
{
if (a[i].v!=a[i-1].v) tt++;
a[i].tag=tt; ccount[tt]++;
}
sort(a+1,a+n+1,cmp2);
int nowh=1,maxh=0,block=0;
for (int i=1; i<=n; i++)
{
ccount[a[i].tag]--;
maxh=max(maxh,a[i].tag);
while (!ccount[nowh]) nowh++;
if (nowh>=maxh) block++;
}
printf("%d\n",block);
}
【D. Spongebob and Squares】
【题目大意】给定一个整数k,求所有子正方形个数和为k的矩形,升序输出长和宽。
【分析】推公式,然后枚举长或者宽,使用set统计……我刚开始脑抽用vector。结果k=1输出了2 1 1 1 1
代码:
//n列m行网格(m<=n)子正方形个数——(3*n-m+1)*(m*(m+1))/6
#include <cstdio>
#include <algorithm>
#include <set>
using namespace std;
set<pair<long long,long long> > s;
set<pair<long long,long long> >::iterator it;
int main()
{
long long xx;
scanf("%I64d",&xx); xx*=6;
long long m=0;
while (++m<2000000)
{
long long x=xx;
if (x%m || x%(m+1)) continue;
x/=m,x/=m+1; x+=m-1;
if (x%3) continue;
long long n=x/3;
if (n<m) break;
s.insert(make_pair(m,n));
s.insert(make_pair(n,m));
}
printf("%d\n",s.size());
for(it=s.begin(); it!=s.end(); it++)
printf("%I64d %I64d\n",it->first,it->second);
}
【D. Spongebob and Squares】
【题目大意】有一个以1为根的树,给出m条树上的边及q组LCA关系(a,b,c)即c为a和b的祖先,求符合条件的树的数量。
【分析】神TM状压DP……我太水了于是乎写了记忆化,打比赛时连题目都没看懂……
代码:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#define mk make_pair
using namespace std;
typedef long long LL;
int n,m,q;
vector<pair<int,int> > lca[14];
int c[14][14],mark[14],obey[14][1<<13];
LL f[14][14][14][1<<13];
LL calc(int fa,int u,int v,int cv)
{
if(f[fa][u][v][cv]!=-1) return f[fa][u][v][cv];
if (v==n)
{
f[fa][u][v][cv]=(cv==0);
return f[fa][u][v][cv];
}
if(v==u || (cv&1<<v)==0)
{
if(c[u][v]&&(v!=fa))return 0;
f[fa][u][v][cv]=calc(fa,u,v+1,cv);
return f[fa][u][v][cv];
}
LL ret=0;
for (int m=cv; m>0; m--)
{
m&=cv;
if(obey[u][m] && ((mark[v]|m)==m))
ret+=calc(u,v,0,m-(1<<v))*calc(fa,u,v+1,cv-m);
}
if (!(c[u][v] && (v!=fa))) ret+=calc(fa,u,v+1,cv);
f[fa][u][v][cv]=ret;
return ret;
}
int main()
{
scanf("%d%d%d",&n,&m,&q);
int x,y,z;
for (int i=0;i<m;i++)
{
scanf("%d%d",&x,&y); x--;y--;
c[x][y] = c[y][x] = true;
}
for (int i=0; i<q; i++)
{
scanf("%d%d%d",&x,&y,&z); x--;y--;z--;
lca[z].push_back(mk(x,y));
}
for (int i=0;i<n;i++)
{
mark[i] = 1<<i;
for (int j=0; j<lca[i].size(); j++)
{
pair<int,int> x=lca[i][j];
mark[i]|=1<<x.first|1<<x.second;
}
for (int s=(1<<n)-1; s>0; s--)
if (!(s&1<<i))
{
obey[i][s]=1;
for (int j=0; j<lca[i].size(); j++)
{
pair<int,int> x=lca[i][j];
if ((s&1<<x.first) && (s&1<<x.second)) { obey[i][s]=0; break; }
}
}
}
memset(f,-1,sizeof f);
LL ans=calc(0,0,0,(1<<n)-2);
printf("%I64d\n",ans);
}