传送门:杭电6511-6521
目录
HDU6517 Bring Bring big teacher brother
HDU6511 Min-Max
题意:有一个长度为n的随机排列以及m个min、max操作。问最后一个操作的结果的期望 * n! 的结果。
思路:把一组数组按大于等于k与否用1\0表示,再按操作来一遍,如果结果为1,说明可行。而如果这个01数组有x个1,那么它对应的正常数组有x!*(n-x)!个。
#include<iostream>
#include<cstring>
#include<cstdio>
#define ll long long
using namespace std;
bool a[1<<16][16];
ll fac[16];
bool b[1001];
int n,m;
struct op{
bool oper,flagx,flagy;//oper表示是否max,flag表示是否数组a、b,
int x,y;
}op[1001];
void pre()
{
memset(a,0,sizeof(a));
int x=1<<n;
for(int i=0;i<x;i++)
for(int j=1,t=i;j<=n;j++,t>>=1)
a[i][j]=t&1;
}
void getfac()
{
fac[0]=1;
for(int i=1;i<=15;i++)
{
fac[i]=fac[i-1]*(ll)i;
}
}
bool Find(int i) //对a[i]数组做模拟运算
{
for(int j=1;j<=m;j++)
{
if(op[j].oper)
{
if(op[j].flagx&&op[j].flagy) b[j]=max(a[i][op[j].x],a[i][op[j].y]);
else if(op[j].flagx&&!op[j].flagy) b[j]=max(a[i][op[j].x],b[op[j].y]);
else if(!op[j].flagx&&!op[j].flagy) b[j]=max(b[op[j].x],b[op[j].y]);
else b[j]=max(b[op[j].x],a[i][op[j].y]);
}
else
{
if(op[j].flagx&&op[j].flagy) b[j]=min(a[i][op[j].x],a[i][op[j].y]);
else if(op[j].flagx&&!op[j].flagy) b[j]=min(a[i][op[j].x],b[op[j].y]);
else if(!op[j].flagx&&!op[j].flagy) b[j]=min(b[op[j].x],b[op[j].y]);
else b[j]=min(b[op[j].x],a[i][op[j].y]);
}
}
return b[m];
}
int getnum(int i)
{
int ans=0;
for(int j=1;j<=n;j++)
if(a[i][j]) ans++;
return ans;
}
int main()
{
string str;
char x,y;
int p,q;
getfac();
while(scanf("%d%d",&n,&m)!=EOF)
{
pre();
ll ans=0;
for(int i=1;i<=m;i++)
{
cin>>str>>x>>p>>y>>q;
if(str=="max") op[i].oper=1;
else op[i].oper=0;
if(x=='a') op[i].flagx=1;
else op[i].flagx=0;
if(y=='a') op[i].flagy=1;
else op[i].flagy=0;
op[i].x=p;op[i].y=q;
}
for(int i=0;i<(1<<n);i++)
{
if(Find(i))
{
int cnt=getnum(i);
ans+=fac[cnt]*fac[n-cnt];
}
}
cout<<ans<<endl;
}
return 0;
}
HDU6512 Triangle
题意:给你n根棍子,问你是否有其中三根可以组成三角形。
思路:不能组成三角形的数至少构成斐波那契数列。故我们可以算出2的32次方对应第x个斐波那契数,那么当输入n>x时,必然输出YES,否则进行排序,判断是否有a[i]+a[i+1]>a[i+2]。
//第50个斐波那契数已经超过int的限度了。
//如果用三次循环和break也能通过。
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define ll long long
using namespace std;
int main()
{
int n;
int a[5000005];
while(cin>>n)
{
for(int i=0;i<n;i++) scanf("%d",&a[i]); //cin超时
if(n>50) cout<<"YES"<<endl;
else
{
bool flag=0;
sort(a,a+n);
for(int i=0;i<n-2;i++)
if(a[i]+a[i+1]>a[i+2])
{
flag=1;
break;
}
if(flag) cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}
}
return 0;
}
HDU6513 Reverse it
题意:有一个n行m列的卡牌阵,每个位置是0或1,0代表卡牌背面朝上,1代表卡牌正面朝下。每次可以选择一个小矩阵,把这个矩阵内所有卡牌翻转,问最后可以得到多少本质不同的卡牌阵。
HDU6514 Monitor
题意:在一个面积不超过n*m的矩形上,有p个矩形A,问之后的q个矩形B能否被之前的A全部覆盖。
思路:数据范围超大,用到了二维前缀和,所谓二维前缀和既是v[i,j]表示从(0,0)到(i,j)的面积。
#include<iostream>
#include<cstring>
#include<cstdio>
#include<stack>
#include<algorithm>
#define ll long long
#define MAX 10000007
using namespace std;
int v[MAX];
int m,n;
void add(int i,int j,int k)
{
if(i>m||j>n) return;
v[(i-1)*n+j]+=k;
}
int query(int i,int j)
{
if(i==0||j==0) return 0;
return v[(i-1)*n+j];
}
void Print()
{
for(int i=1;i<=m;i++)
{
for(int j=1;j<=n;j++) cout<<v[(i-1)*n+j]<<' ';
cout<<endl;
}
}
int main()
{
int k,x1,x2,y2,y1;
while(cin>>m>>n)
{
memset(v,0,sizeof(v));
cin>>k;
while(k--)
{
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
add(x1,y1,1);
add(x2+1,y2+1,1);
add(x1,y2+1,-1);
add(x2+1,y1,-1);
}
//二维前缀和
for(int i=1;i<=m;i++)
for(int j=1;j<=n;j++)
v[(i-1)*n+j]+=query(i-1,j)+query(i,j-1)-query(i-1,j-1);
//Print();//确定某一点有无被覆盖
for(int i=1; i<=n*m; i++)
if(v[i]) v[i]=1;
//再求前缀和
for(int i=1;i<=m;i++)
for(int j=1;j<=n;j++)
v[(i-1)*n+j]+=query(i-1,j)+query(i,j-1)-query(i-1,j-1);
cin>>k;
while(k--)
{
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
int tmp=query(x2,y2)+query(x1-1,y1-1)-query(x1-1,y2)-query(x2,y1-1);
if(tmp==((x2-x1+1)*(y2-y1+1))) cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}
}
return 0;
}
HDU6515 Coding problem
题意:将字符串每个字符ASCII的二进制翻转码组成的字符串以每6个一组输出。
思路:模拟
#include<iostream>
#include<cstring>
#include<cstdio>
#include<stack>
#include<algorithm>
#define ll long long
#define p (i*8+j)/6
using namespace std;
int main()
{
string a;
int ans[400004];
while(cin>>a)
{
memset(ans,0,sizeof(ans));
int n=a.length();
for(int i=0;i<n;i++)
for(int j=0;j<8;j++,a[i]>>=1)
ans[p]=(ans[p]<<1)+(a[i]&1);
for(int i=0;i<(n/3*4);i++)
cout<<ans[i]<<' ';
}
return 0;
}
HDU6516 Network
HDU6517 Bring Bring big teacher brother
HDU6518 Clumsy Keke
题意:给定一个立方堆的三视图,求它的体积(有多种可能则输出最大)。
思路:如果下面的代码不好理解的话,可以考一下切割,即建立一个v[100][100][100],初始为1,慢慢切割,最后统计。
#include<iostream>
#include<cstring>
#include<cstdio>
#include<stack>
#include<algorithm>
#define ll long long
#define p (i*8+j)/6
using namespace std;
int main()
{
int x,y,z;
while(cin>>x>>y>>z)
{
int ans=0;
bool f[100][100],t[100][100],s[100][100];
for(int i=0;i<x;i++)
for(int j=0;j<y;j++) cin>>f[i][j];
for(int i=0;i<y;i++)
for(int j=0;j<z;j++) cin>>t[i][j];
for(int i=0;i<z;i++)
for(int j=0;j<x;j++) cin>>s[i][j];
for(int i=0;i<x;i++)
for(int j=0;j<y;j++)
for(int k=0;k<z;k++)
if(f[i][j]&&t[j][k]&&s[k][i]) ans++;
cout<<ans<<endl;
}
return 0;
}
HDU6519 Enlarge it
题意:输入一个字符矩阵,把它放大k倍输出。
#include<iostream>
#include<cstring>
#include<cstdio>
#include<stack>
#include<algorithm>
#define ll long long
using namespace std;
int main()
{
int m,n,k;
char a[100][100],b[1000][1000];
while(cin>>m>>n>>k)
{
for(int i=0;i<m;i++)
for(int j=0;j<n;j++)
cin>>a[i][j];
for(int i=0;i<m*k;i++)
{
for(int j=0;j<n*k;j++)
cout<<a[i/k][j/k];
cout<<endl;
}
}
return 0;
}
HDU6520 Silly Keke
HDU6521 Party
题意:有n个人,开m次派对,每次派对每对人会相互认识对方。对于每一次派对,我们要求出新认识的pair的数量。