比赛:新疆大学ACM-ICPC程序设计竞赛五月月赛(同步赛)
队伍出题:7/10
个人出题:4
读题还是大问题。好几道英文题都是问了别人的题意。。。说几道水题。。。
A(Red Rover):给你一个字符串,其中原本这个字符串是含字母M的,之后用一段字符替换了每个M后形成了输入给的字符串。你要把它还原,使得原来包含M的串的长度+替换字母M的串的长度最小。
数据范围很小,直接贪心即可。
但是有细节必须注意:
1、字符串长度为1的时候直接输出1。
2、可以不换。也就是说不加密。
代码就不贴了。
B(杨老师的游戏):给你一个数n,你要用1~9这九个数字组成A*B-C的形式,每个数字只能用一次,求结果等于n的方法总数。
虽然是暴力,但是费了我老半天劲。。。最后还是决定先预处理完所有的合法情况。。。这里用到了求全排列的dfs,这里贴一下代码。
代码:
#include
#define ll long long
using namespace std;
const int maxn=400010;
const ll mo=1e9+7;
int c[15][15],ans;
int tmp,cnt;
int flag;
int d[1000010];
int n,m,x,y,z,l,bb,t,f,k,xx,yy,h;
char ch[maxn];
int b[10];
void dfs(int b[],int len,int k)
{
if(len == k)
{
int tmp=0;
int num=0;
int cnt=0;
for(int i=0;i<7;i++)
{
for(int j=i+1;j<8;j++)
{
tmp=0;num=0;cnt=0;
for(int k=0;k<9;k++)
{
if(k<=i) tmp=tmp*10+b[k];
else if(k<=j) num=num*10+b[k];
else cnt=cnt*10+b[k];
}
tmp=tmp*num-cnt;
if(tmp>=0&&tmp<=1000000)d[tmp]++;
}
}
}
else
{
for(int idx = k ; idx <= len; ++idx)
{
swap(b[idx],b[k]);
dfs(b,len,k + 1);
swap(b[idx],b[k]);
}
}
}
int main(){
//freopen("holes.in","r",stdin);
//freopen("holes.out","w",stdout);
f=0;
memset(d,0,sizeof(d));
for(int i=1;i<=10;i++) b[i-1]=i;
dfs(b,8,0);
int T,cas;
scanf("%d",&n);
ans=0;
printf("%d\n",d[n]);
return 0;
}
C(勤奋的杨老师):中文题。。。题意不用说了吧。
DP。但不是裸的dp,需要一些优化,这道题队友过得。
F(猴子排序的期望):就是求n!/各个字母出现的数量的阶乘
需要用java大数。自己的java太菜,写的RE,早就学会java的队友没来,于是偷了隔壁的代码。。。
H(XOR):给你n个点权值分别为0~n-1,你要添加一些边使他们成为一个联通块,费用为两点的异或值。n=20000
其实只需要预处理20000以内的所有情况O(1)输出即可。对于2个点,费用为1,>=3的点找小于它的一个异或值最小的点连上即可。
其实还有更牛的解法,就是0-n-1的lowbit值加起来。。。据说是打表找出来的规律。。。
J(Most Powerful):状压dp专题的原题。。。简单状压dp,我就说怎么看着这么熟悉呢。。。想起来后敲了一发秒过