比赛:新疆大学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 <bits/stdc++.h> #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,我就说怎么看着这么熟悉呢。。。想起来后敲了一发秒过