这里附上题目链接:[USACO08DEC]Patting Heads S。
~~手动分割~~
题目
思路解析
1.暴力搜索
- 将每头牛拿的数字存下。
- 分别将每头牛拿的数作为被除数,逐一检查剩下的n-1头牛能否整除被除数。
代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int n,a[100002];//共有n头奶牛
int pat_number[1000002];//拿着数字i的牛需要拍打pat_number[i]头牛
int main()
{
int i,j;
//输入数据
scanf("%d",&n);
for(i=1;i<=n;++i)
{
scanf("%d",a+i);//输入数字a[i]
}
//
for(i=1;i<=n;++i)
{
if(pat_number[a[i]])//若拿着数字i的牛所需拍打的次数已经计算过
{
continue;
}
for(j=1;j<i;++j)
{
if(a[i]%a[j]==0)
{
pat_number[a[i]]++;
}
}
for(j=i+1;j<=n;++j)
{
if(a[i]%a[j]==0)
{
pat_number[a[i]]++;
}
}
}
//输出结果
for(i=1;i<=n;i++)
{
printf("%d\n",pat_number[a[i]]);
}
return 0;
}
2.构造
每头牛手上都拿了一个数字。
从0次开始,只要数字 i 多出现一次,手上拿着的数为 i 的倍数的牛就会多拍拿着 i 的牛一次。
- 先找出所有牛拿的数字中最大的数字m。
scanf("%d",a+i);//输入数字a[i]
m=max(m,a[i]);
- 统计每个数字出现的次数。
occurrence_number[*(a+i)]++;//数字a[i]出现的次数加一
- 从1到m,逐一判断。只要数字 i 至少出现了一次,就把所有拿着i的倍数的牛所需拍打的牛的数目加上 i 的出现次数。
//计算并输出结果
for(i=1;i<=m;++i)
{
if(occurrence_number[i])//若数字i至少出现了一次
{
for(j=1;j*i<=m;j++)
{
pat_number[i*j]+=occurrence_number[i];//拿着数字i*j的牛需要多拍occurrence_number[i]次
}
}
}
- 将所有牛所需拍打的次数减一,因为在计算时每头牛多拍了自己。
for(i=1;i<=n;++i)
{
printf("%d\n",pat_number[a[i]]-1);//在计算时每头牛多拍了自己,所以要减掉自己
}
AC代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define max(A,B) ((A)>(B)?(A):(B))
int n,a[100002],m;//共有n头奶牛
int occurrence_number[1000002];//数字i出现了occurrence_number[i]次
int pat_number[1000002];//拿着数字i的牛需要拍打pat_number[i]头牛
int main()
{
int i,j;
//输入数据并计算每个数出现的次数
scanf("%d",&n);
for(i=1;i<=n;++i)
{
scanf("%d",a+i);//输入数字a[i]
m=max(m,a[i]);
occurrence_number[*(a+i)]++;//数字a[i]出现的次数加一
}
//计算并输出结果
for(i=1;i<=m;++i)
{
if(occurrence_number[i])//若数字i至少出现了一次
{
for(j=1;j*i<=m;j++)
{
pat_number[i*j]+=occurrence_number[i];//拿着数字i*j的牛需要多拍occurrence_number[i]次
}
}
}
for(i=1;i<=n;++i)
{
printf("%d\n",pat_number[a[i]]-1);//在计算时每头牛多拍了自己,所以要减掉自己
}
return 0;
}