A 首先读题不认真没有仔细的读数据范围,以为人家学校给大一训练的很简单轻敌了,结果交了2次后才发现是字符串的比较,唉 傻逼了。
我用的是C++ STL string 比较容易,由于记不住什么qsort这神马的排序,写了个cmp就很容易过了。。。
#include<functional>
#include<algorithm>
#include<iostream>
#include<fstream>
#include<sstream>
#include<iomanip>
#include<numeric>
#include<cstring>
#include<cassert>
#include<cstdio>
#include<string>
#include<vector>
#include<bitset>
#include<queue>
#include<stack>
#include<cmath>
#include<ctime>
#include<list>
#include<set>
#include<map>
using namespace std;
string s[150];
bool cmp(const string & a,const string & b){
if(a.size()==b.size()) return a<b;
return a.size()<b.size();
}
int main(){
int n;
while(~scanf("%d",&n)){
for(int i=0;i<n;i++) cin>>s[i];
sort(s,s+n,cmp);
for(int i=0;i<n;i++)
cout<<s[i]<<endl;
}
return 0;
}
B 这题说的很清楚,就是字符串处理找神马的前缀。
两种解法:
1、建立字典树:ans=2*节点数+n(因为要输出n次)-最长链长度。用贪心的想法想局部,然后跳出来全局看,就得到这个结论了;
2、将所有的单词按字典序排序,然后遍历;
*/
要不说我很弱,Tire看了么看明白也就只能用第二种方法了,过几天再把Tire贴上来。(占个坑)
#include<functional>
#include<algorithm>
#include<iostream>
#include<fstream>
#include<sstream>
#include<iomanip>
#include<numeric>
#include<cstring>
#include<cassert>
#include<cstdio>
#include<string>
#include<vector>
#include<bitset>
#include<queue>
#include<stack>
#include<cmath>
#include<ctime>
#include<list>
#include<set>
#include<map>
using namespace std;
string s[10005];
inline int cmp(string a,string b)
{
int i;
for(i=0;i<a.length()&&i<b.length()&&a[i]==b[i];i++);
return a.length()-i+b.length()-i;
}
int main()
{
int n,i;
while(~scanf("%d",&n))
{
for(i=0;i<n;i++) cin>>s[i];
sort(s,s+n);
int sum=s[0].length()+1;
int ANS=s[0].length();
for(i=1;i<n;i++)
{
sum+=cmp(s[i],s[i-1])+1;
if(s[i].length()>ANS)
ANS=s[i].length();
}
printf("%d\n",sum+s[n-1].length()-ANS);
}
return 0;
}
C 这题我苦逼了。。。交了两次 唉 处理字符串不够细心,白白罚时。坑,真心很坑。。。
#include<functional>
#include<algorithm>
#include<iostream>
#include<fstream>
#include<sstream>
#include<iomanip>
#include<numeric>
#include<cstring>
#include<cassert>
#include<cstdio>
#include<string>
#include<vector>
#include<bitset>
#include<queue>
#include<stack>
#include<cmath>
#include<ctime>
#include<list>
#include<set>
#include<map>
using namespace std;
char a[101], str[101];
int main()
{
int i, j;
int t;
scanf("%d", &t);
getchar();
while (t--)
{
gets(a);
int len=strlen(a);
i=0;j=0;
while(a[i]==32) i++;
if(islower(a[i])) str[j++]=a[i]-32;
else str[j++]=a[i];
i++;
while(i<len-1)
{
if(a[i]==32&&a[i+1]!=32)
{
if(islower(a[i+1])) str[j++]=a[i+1]-32;
else str[j++]=a[i+1];
}
i++;
}
str[j]='\0';
puts(str);
}
return 0;
}
D 这题傻逼了,时间到了 改明白了。。(思路应该是KMP 的Next数组性质,KMP 的算法。(我用的是LRJ的MP算法)),调了很久只因为花括号的地方放错了,所以一直WA、还是不细心啊。
#include<functional>
#include<algorithm>
#include<iostream>
#include<fstream>
#include<sstream>
#include<iomanip>
#include<numeric>
#include<cstring>
#include<cassert>
#include<cstdio>
#include<string>
#include<vector>
#include<bitset>
#include<queue>
#include<stack>
#include<cmath>
#include<ctime>
#include<list>
#include<set>
#include<map>
using namespace std;
const int MAXN=1000005;
char T[MAXN];
int F[MAXN];
void getfail(char *P,int *f)// MP算法
{
f[0]=f[1]=0;
int m=strlen(P);
for(int i=1;i<m;i++){
int j=f[i];
while(j&&P[i]!=P[j]) j=f[j];
f[i+1]=(P[i]==P[j]?j+1:0);
}
}
int main(){
char ch;
int t;
scanf("%d%*",&t);
while(t--){
scanf("%s",T);
int len=strlen(T);
getfail(T,F);
bool flag=true;
for(int i=2;i<=len;++i){
if(F[i]>0&&i%(i-F[i])==0){
printf("%d %d\n",i,i/(i-F[i]));flag=false;
}
}
if(flag) cout<<"NO\n";
cout<<endl;
}
return 0;
}
E 说是数学问题也可以。由于题中说的选定序列中的2个数ai,aj当然i!=j,然后它将ai増加1,将aj减少1,即ai=ai+1, aj=aj-1,以上的操作会改变该序列中的两个不同的元素,Tailmon可以进行上述操作无限次,只求将该序列中的数变成某一个数越多越好。现在他想知道通过上述操作无限多次,最多能得到多少个相同的数。
本质:无论你进行了多少次的ai=ai+1, aj=aj-1,其序列的Sum值是不会改变的,那么也就转化为了求Sum mod N 是否为0 或 1的问题。
if (Sum mod N = = 0 ) cout<<N<<endl;
else cout<< N-1<<endl;
#include<functional>
#include<algorithm>
#include<iostream>
#include<fstream>
#include<sstream>
#include<iomanip>
#include<numeric>
#include<cstring>
#include<cassert>
#include<cstdio>
#include<string>
#include<vector>
#include<bitset>
#include<queue>
#include<stack>
#include<cmath>
#include<ctime>
#include<list>
#include<set>
#include<map>
using namespace std;
int a[100005];
int main()
{
int n;
while(~scanf("%d",&n)){
int sum=0;
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
for(int i=1;i<=n;i++)
sum+=a[i];
if(sum%n) printf("%d\n",n-1);
else printf("%d\n",n);
}
return 0;
}
F 这题又是字符串的模拟。。。细心就好。坑爹的字符串,伤不起。
#include<functional>
#include<algorithm>
#include<iostream>
#include<fstream>
#include<sstream>
#include<iomanip>
#include<numeric>
#include<cstring>
#include<cassert>
#include<cstdio>
#include<string>
#include<vector>
#include<bitset>
#include<queue>
#include<stack>
#include<cmath>
#include<ctime>
#include<list>
#include<set>
#include<map>
using namespace std;
char s[5000];
char t[5000];
int T,i;
int cnt=1;
bool flag;
int main()
{
scanf("%d",&T);
while(T--)
{
scanf("%s",s);
flag=false;
int len=strlen(s);
int tmp=0;
for(i=2;i<len;i++){
if(flag==false&&s[i-2]==':'&&s[i-1]=='/'&&s[i]=='/'){
flag=true;
continue;
}
if(flag&&(s[i]=='/'||s[i]==':')) break;
if(flag) t[tmp++]=s[i];
}
t[tmp]='\0';
printf("Case #%d: %s\n",cnt++,t);
}
return 0;
}
G 终于来了到有难度的题,其实还是蛮简单的。给出函数,然后给出N个数a1,a2,a3……,问你其中F(ai)和F(aj) 相同的对数。其实就是求F(X) 二进制中X的1的个数。。。
#include<functional>
#include<algorithm>
#include<iostream>
#include<fstream>
#include<sstream>
#include<iomanip>
#include<numeric>
#include<cstring>
#include<cassert>
#include<cstdio>
#include<string>
#include<vector>
#include<bitset>
#include<queue>
#include<stack>
#include<cmath>
#include<ctime>
#include<list>
#include<set>
#include<map>
using namespace std;
int a[100003];
int check(int i){
if(i==0)return 0;
else return check(i>>1)+(i&1);
}
int main(){
int n,i;
while(~scanf("%d",&n)){
for(i=0;i<n;i++)
scanf("%d",&a[i]);
for(i=0;i<n;i++)
a[i]=check(a[i]);
double ans=0.0,t=1.0;
sort(a,a+n);
for(i=1;i<n;i++)
if(a[i]==a[i-1]) t+=1;
else{
ans+=((t*(t-1))/2);t=1;
}
{ans+=((t*(t-1))/2);t=1;}
printf("%.0lf\n",ans);
}
return 0;
}
H 这题很傻逼。。。据说尼玛的3种解法(set+hash、用trie图统计字串、后缀数组)。。。而我傻逼的写了其中最长的后缀数组。这几天一直再看后缀数组,没想到这题成为了第一个A后缀数组的题。题目说的很清楚就是要寻找满足某一条件的不同字串个数。。。用后缀数组统计子串。。。。坑爹的是我废了很大劲写完了得到了FB,结果唉,人家把内存改大了,救了很多RE的孩子。。。真心坑。
#include<algorithm>
#include<cstring>
#include<cstdio>
using namespace std;
const int MAXN=2010;
char r[MAXN];
int sa[MAXN];
int wa[MAXN],wb[MAXN],wv[MAXN],ws[MAXN];
int height[MAXN],rank[MAXN];
int sum[2000],k;
inline bool cmp(int *r,int a,int b,int len){
return r[a]==r[b]&&r[a+len]==r[b+len];
}
void SA(int n,int m){
int i,j,p,*x=wa,*y=wb,*t;
for(i=0;i<m;i++)
ws[i]=0;
for(i=0;i<n;i++)
ws[x[i]=r[i]]++;
for(i=1;i<m;i++)
ws[i]+=ws[i-1];
for(i=n-1;i>=0;i--)
sa[--ws[x[i]]]=i;
for(j=p=1;p<n;j<<=1,m=p){
for(p=0,i=n-j;i<n;i++)
y[p++]=i;
for(i=0;i<n;i++){
if(sa[i]>=j)
y[p++]=sa[i]-j;
}
for(i=0;i<m;i++)
ws[i]=0;
for(i=0;i<n;i++)
ws[wv[i]=x[y[i]]]++;
for(i=1;i<m;i++)
ws[i]+=ws[i-1];
for(i=n-1;i>=0;i--)
sa[--ws[wv[i]]]=y[i];
for(t=x,x=y,y=t,x[sa[0]]=0,p=i=1;i<n;i++)
x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;
}
}
void Height(int n){
int i,j,k=0;
for(i=1;i<=n;i++)
rank[sa[i]]=i;
for(i=0;i<n;height[rank[i++]]=k)
for(k?k--:0,j=sa[rank[i]-1];r[i+k]==r[j+k];k++);
}
void solve(int n){
int i,j;
int ans=0;
for(i=1;i<=n;i++){
for(j=sa[i]+height[i];j<n;j++){
if(sum[j+1]-sum[sa[i]]>k)break;
ans++;
}
}
printf("%d\n",ans);
}
int main(){
while(~scanf("%s",r)){
int i,j,n;
char str[50];
memset(sum,0,sizeof(sum));
scanf("%s",str);
scanf("%d",&k);
n=strlen(r);
for(i=1;i<=n;i++)
sum[i]=sum[i-1]+(str[r[i-1]-'a']=='0');
memset(height,0,sizeof(height));
SA(n+1,130);
Height(n);
solve(n);
}
return 0;
}
总结:比赛还是思维反应的比较慢,还需要加强!!!算法估计的不是很准确。慢慢提高吧。