第一题:Little Elephant and Function
题意:通过不断调用一个交换函数可以把一个数字序列变成升序,问原始的数字序列是什么。
题解:逆向模拟即可。
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int num[1005];
int n;
void f(int x)
{
if(x>n) return;
f(x+1);
swap(num[x-1],num[x]);
}
int main()
{
scanf("%d",&n);
if(n==1)
{
printf("1\n");
return 0;
}
for(int i=1;i<=n;++i) num[i]=i;
f(2);
for(int i=1;i<=n;++i)
if(i==1) printf("%d",num[i]);
else printf(" %d",num[i]);
puts("");
return 0;
}
第二题:Little Elephant and Numbers
题意:给你一个数N,要求找出数d,d能整除N,同时d和N至少包含一个相同的数字,问这样的d有多少个。
题解:求出N的因子,再判断有多个因子符合要求。
代码:
#include<cstdio>
#include<cstring>
using namespace std;
bool flag[11];
bool check(int x)
{
for(int i=x;i>0;i/=10) if(flag[i%10]) return true;
return false;
}
int main()
{
int n,summ=0;
scanf("%d",&n);
memset(flag,false,sizeof(flag));
for(int i=n;i>0;i/=10) flag[i%10]=true;
for(int i=1;i*i<=n;++i)
{
if(n%i==0)
{
if(check(i)) summ++;
if(i==n/i) continue;
if(check(n/i)) summ++;
}
}
printf("%d\n",summ);
return 0;
}
题意:给出一个数组,问是否是由一个已排序的数组经过交换至多一对数得到。
题解:将给定的数组排序后与元数组比较,若有多于两个位置不同则输出“YES”,否则将原数组两个位置的数字交换后比较是否与排序后数组相同。
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int a[100005],b[100005];
int cnt[3];
int main()
{
int n;
scanf("%d",&n);
for(int i=0;i<n;++i)
{
scanf("%d",a+i);
b[i]=a[i];
}
sort(b,b+n);
int ans=0;
for(int i=0;i<n;++i)
{
if(a[i]!=b[i])
{
if(ans>=2)
{
puts("NO");
return 0;
}
cnt[ans++]=i;
}
}
if(ans<1)
puts("YES");
else
{
if(a[cnt[0]]==b[cnt[1]]&&a[cnt[1]]==b[cnt[0]])
puts("YES");
else
puts("NO");
}
return 0;
}
第四题:Little Elephant and Array
题意:一个n个数字的数字序列,同时有m次询问,问在a,b之间符合数字x刚好出现x次的数有多少个。
题解:由于符合条件的数总数不超过450个,我们可以从此下手,先统计每个数字出现的次数,剔除不可能符合条件的数字,然后h[i][j]表示第i个数字在0~j出现的次数,询问的时候只要对i个数字将0~a-1和0~b两个区间内第i个数出现的次数相减就得到第i个数字在a~b中出现的次数,统计即可。
代码:
#include<cstdio>
#include<cstring>
#include<map>
#define MAX 100005
using namespace std;
struct node
{
int x,num;
} temp;
int s[MAX],b[450],h[MAX][450];
map<int,struct node> mat;
int main()
{
int n,m,k,t;
for(; ~scanf("%d%d",&n,&t);)
{
mat.clear();
for(int i=1; i<=n; ++i)
{
scanf("%d",&s[i]);
//统计一个数出现的次数
if(mat.count(s[i])==0)
{
temp.x=s[i];
temp.num=1;
mat.insert(make_pair(s[i],temp));
}
else
(mat.find(s[i])->second.num)++;
}
k=0;
//查找可能符合条件的数
for(map<int,struct node>::iterator it=mat.begin(); it!=mat.end(); ++it)
if(it->second.x<=it->second.num) b[++k]=it->second.x;
for (int i=1; i<=k; ++i)
{
h[0][i]=0;
for (int j=1; j<=n; ++j)
if (s[j]==b[i]) h[j][i]=h[j-1][i]+1;
else h[j][i]=h[j-1][i];
}
int l,r,ans;
for(;t--;)
{
ans=0;
scanf("%d%d",&l,&r);
for (int i=1; i<=k; ++i)
if (h[r][i]-h[l-1][i]==b[i]) ans++;
printf("%d\n",ans);
}
}
return 0;
}
第五题: Little Elephant and Shifts
题意:给你一个1~n组成的n个数字的数列a,再给一个a数列的另一种排序方式形成的数列b,两个数列的距离为最小的|i - j|, ai = bj。问将b循环左移n次,每次循环左移后a与b的距离是多少。
题解:每次求的最小距离都是最大的负数与最小的非负数中绝对值最小的一个。
代码:
#include<cstdio>
#include<algorithm>
#include<set>
using namespace std;
#define MAX 100010
int a[MAX],b[MAX],hashx[MAX],d[MAX];
multiset<int> s;
int main()
{
int n,t,res;
scanf("%d",&n);
for(int i=0; i<n; ++i)
{
scanf("%d",a+i);
hashx[a[i]]=i;//存放数字在a中的位置
}
for(int i=0; i<n; ++i)
{
scanf("%d",b+i);
s.insert(i-hashx[b[i]]);//插入相同数字的距离
}
for(int i=0; i<n; ++i)
{
multiset<int>::iterator it=s.lower_bound(i);//查找大于等于i的第一个数
res=0xfffff;
if(it!=s.end()) res=min(res,(*it)-i);//非负数中最小的数的绝对值
if(it!=s.begin()) res=min(res,i-(*(--it)));//负数中的最大的数的绝对值
printf("%d\n",res);
//模拟旋转
t=b[i];
s.erase(s.find(i-hashx[t]));
s.insert((i+n)-hashx[t]);
}
return 0;
}
来源:http://blog.youkuaiyun.com/acm_ted/article/details/7943188