Mod | ||||||
| ||||||
Description | ||||||
Kim刚刚学会C语言中的取模运算(mod)。他想要研究一下一个数字A模上一系列数后的结果是多少。帮他写个程序验证一下。 | ||||||
Input | ||||||
第一行一个整数T代表数据组数。 接下来T组数据,第一行一个整数n,接下来n个数字ai 接下来一行一个整数m,接下来m个数字bi。 | ||||||
Output | ||||||
对于每个bi,输出bi%a1%a2%...%an 。 | ||||||
Sample Input | ||||||
1 4 10 9 5 7 5 14 8 27 11 25 | ||||||
Sample Output | ||||||
4 3 2 1 0 | ||||||
Hint | ||||||
在C语言中,A mod B 是 a%b 样例解释: 14%10%9%5%7=4 8%10%9%5%7=3 ... 数据范围: 1<=n<=100000 1<=m<=100000 1<=ai<=1000000000 0<=bi<=1000000000 | ||||||
Source | ||||||
"科林明伦杯"哈尔滨理工大学第六届程序设计团队赛 |
思路:
1、首先考虑对于一个数num,如果其之前已经对某个数x取过膜了,那么得到的数一定在【0~x】之间,那么我们肯定再对比x大的数取模就没有意义了。
所以对于数组a,我们肯定只要按照顺序得到一个递减序列,将不需要进行取模的部分删除掉。
2、此时数组a是一个递减序列,那么对于每一个查询x,找到a数组中第一个小于等于x的数,然后将x进行取模之后得到的数字,继续进行二分。
知道不能找到合法位子为止,那么最终取模得到的数x就是正解啦。
Ac代码:
#include<stdio.h>
#include<string.h>
using namespace std;
int n;
int a[1080000];
int Getpos(int ss)
{
if(ss>=n)return -1;
int ans=-1;
int l=ss;
int r=n;
while(r-l>=0)
{
int mid=(l+r)/2;
if(a[mid]<=a[ss])
{
ans=mid;
r=mid-1;
}
else l=mid+1;
}
return ans;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int tmpn;
scanf("%d",&tmpn);
n=0;
for(int i=0;i<tmpn;i++)
{
int x;
scanf("%d",&x);
if(i==0||x<a[n-1])a[n++]=x;
}
int q;
scanf("%d",&q);
while(q--)
{
int num;
int prepos=0;
scanf("%d",&num);
while(1)
{
int pos=Getpos(prepos);
if(pos==-1)break;
else
{
num=num%a[pos];
prepos=pos+1;
}
}
printf("%d\n",num);
}
}
}