今天和fwj和小萌virtual了一场比赛,写下解题报告。
这套题也就最后一题有意思点。
A.不解释,排序搞过
#include <stdio.h>
#include <string>
#include <algorithm>
#include <iostream>
using namespace std;
string a[105];
string str,str1;
bool cmp(string x,string y)
{
return x<y;
}
int main()
{
int i,j,n,t,t1;
cin>>str;
cin>>n;
for (i=0;i<n;i++)
{
cin>>a[i];
}
a[n]=str;
sort(a,a+n+1,cmp);
for (i=0;i<=n+1;i++)
{
if (a[i]==str) break;
}
if (i==n+1)
{
cout<<str<<endl;
return 0;
}
str1=a[i+1];
t=str.size();
t1=str1.size();
if (t>=t1)
{
cout<<str<<endl;
return 0;
}
for (i=0;i<t;i++)
{
if (str[i]!=str1[i]) break;
}
if (i<t)
{
cout<<str<<endl;
return 0;
}
cout<<str1<<endl;
return 0;
}
B.蛮麻烦的一题,各种YY,小萌赛后给出一个看起来好像很神的方法,明天催他写解题报告……链接如下:http://blog.danc.co/?p=12
我写的很复杂的样子,不看也罢
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
int main()
{
int i,j;
__int64 t,x,y,ans1,ans2,tt;
scanf("%I64d%I64d",&x,&y);
ans1=ans2=0;
t=1;
for (i=1;;i++)
{
if (x*1.0/t>=0.8 && x*1.0/t<=1.25)
{
if (ans1*ans2<x*t)
{
ans1=x;
ans2=t;
}
else if (ans1*ans2==x*t && ans1<x)
{
ans1=x;
ans2=t;
}
}
tt=1.25*t;
if (tt*1.0/t<0.8) continue;
if (tt<=x)
{
if (ans1*ans2<t*tt)
{
ans1=tt;
ans2=t;
}
else if (ans1*ans2==t*tt && ans1<tt)
{
ans1=tt;
ans2=t;
}
}
t*=2;
if (t>y) break;
}
t=1;
for (i=1;;i++)
{
if (t*1.0/y>=0.8 && t*1.0/y<=1.25)
{
if (ans1*ans2<t*y)
{
ans1=t;
ans2=y;
}
else if (ans1*ans2==t*y && ans1<t)
{
ans1=t;
ans2=y;
}
}
tt=t/0.8;
if (t*1.0/tt<0.8)
{
tt--;
}
if (t*1.0/tt>1.25) continue;
if (tt<=y)
{
if (ans1*ans2<t*tt)
{
ans1=t;
ans2=tt;
}
else if (ans1*ans2==t*tt && ans1<t)
{
ans1=t;
ans2=tt;
}
}
t*=2;
if (t>x) break;
}
printf("%I64d %I64d\n",ans1,ans2);
return 0;
}
C.想法题,要找一个n的排列让相邻的数之差的绝对值两两不相等。
取一个最大一个最小,然后不断往中间取就行了
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
int main()
{
int i,j,n,p,q;
scanf("%d",&n);
p=1;
q=n;
for (i=0;i<n-1;i++)
{
if (i%2==0) printf("%d ",p++);
else printf("%d ",q--);
}
printf("%d\n",p);
return 0;
}
D.hash后冒泡排序统计次数。
#include <stdio.h>
#include <string.h>
#include <map>
#include <vector>
#include <algorithm>
using namespace std;
int a[305];
int b[305];
int c[305];
map< int,vector<int> > m;
int ans[10000005][2];
int main()
{
int i,j,n,up;
scanf("%d",&n);
for (i=0;i<n;i++)
{
scanf("%d",&a[i]);
m[a[i]].push_back(i);
}
for (i=0;i<n;i++)
{
scanf("%d",&b[i]);
c[i]=m[b[i]][m[b[i]].size()-1];
m[b[i]].pop_back();
}
up=0;
for (i=0;i<n;i++)
{
for (j=n-1;j>i;j--)
{
if (c[j]<c[j-1])
{
swap(c[j],c[j-1]);
ans[up][0]=j-1;
ans[up++][1]=j;
}
}
}
printf("%d\n",up);
for (i=0;i<up;i++)
{
printf("%d %d\n",ans[i][0]+1,ans[i][1]+1);
}
return 0;
}
E.状态dp。
官方tutorial表示木有看懂,不过自己YY了个三进制的做法,看懂官方题解的求教,谢谢。
题意是求一个图的生成树的个数,要求生成树的度为1的点的个数为k。
dp[i],i表示一个三进制的状态,第k位为0表示这个点还没有连上,为1表示这个点的度为1,为2表示这个店的度大于1
每次转移在状态上找一个没有连上的点y,再寻找一个已经连上的点x,如果这两个点之间存在边就连上,连上之后显然x的度必须大于1,而y的度肯定等于1,转移就出来了。
但是有一个问题,就是判重。
例如1 ---- 2 ---- 3
这么转移会导致先连1--2再连3和先连2--3再连1是不同的结果,因此会造成重复计算。
观察
1------2----3
|
4
上图,有可能是先连1-2-4再加上3,可能是先连1-2-3再加上4,也可能是先连2-3-4再加上1,因此可以发现,重复计算的次数是得到的图中入度为1的节点的个数(因为每次加入一个节点入度肯定为1),所以dp[i]最后要除掉入读为1的节点的个数。
代码
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
int map[55][55];
int three[15];
int hash[15];
__int64 dp[100000];
int hash1[15];
int n;
int F(int *a)
{
int ret=0,i;
for (i=0;i<n;i++)
{
ret=ret+a[i]*three[i];
}
return ret;
}
int main()
{
int i,j,kk,m,tmp,x,y,k,cnt;
__int64 ans;
scanf("%d%d%d",&n,&m,&kk);
memset(dp,0,sizeof(dp));
three[0]=1;
for (i=1;i<12;i++)
{
three[i]=three[i-1]*3;
}
for (i=0;i<m;i++)
{
scanf("%d%d",&x,&y);
map[x-1][y-1]=1;
map[y-1][x-1]=1;
dp[three[x-1]+three[y-1]]=2;
}
for (i=0;i<three[n];i++)
{
if (dp[i]==0) continue;
tmp=i;
cnt=0;
for (j=n-1;j>=0;j--)
{
if (tmp>=2*three[j])
{
hash[j]=2;
tmp-=three[j]*2;
}
else if (tmp>=three[j])
{
hash[j]=1;
tmp-=three[j];
}
else hash[j]=0;
if (hash[j]==1) cnt++;
}
dp[i]/=cnt;
for (x=0;x<n;x++)
{
for (y=0;y<n;y++)
{
if (hash[x]==0 || hash[y]!=0 || map[x][y]==0) continue;
for (k=0;k<n;k++)
{
hash1[k]=hash[k];
}
hash1[x]=2;
hash1[y]=1;
tmp=F(hash1);
dp[tmp]+=dp[i];
// printf("%d %d\n",tmp,i);
}
}
}
ans=0;
for (i=0;i<three[n];i++)
{
if (dp[i]==0) continue;
// printf("%d %d\n",i,dp[i]);
tmp=i;
for (j=n-1;j>=0;j--)
{
if (tmp>=2*three[j])
{
hash[j]=2;
tmp-=2*three[j];
}
else if (tmp>=three[j])
{
hash[j]=1;
tmp-=three[j];
}
else hash[j]=0;
}
for (j=0;j<n;j++)
{
if (hash[j]==0) break;
}
if (j<n) continue;
cnt=0;
for (j=0;j<n;j++)
{
if (hash[j]==1) cnt++;
}
if (cnt==kk) ans+=dp[i];
}
printf("%I64d\n",ans);
return 0;
}
本文记录了一场虚拟比赛中五道题目的解题过程与思路。题目包括排序、复杂算法、排列组合、哈希与排序及状态动态规划等问题。文章详细介绍了每道题的解题代码与思考过程。
957

被折叠的 条评论
为什么被折叠?



