#22. 【UR #1】外星人
#22. 【UR #1】外星人
2044年,Picks建成了人类第一台基于量子理论的银河系信息传递机。
Picks游遍了宇宙,雇用了 nn 个外星人来帮他作为信息传递机的中转站。我们将外星人依次编号为 11 到 nn,其中 ii 号外星人有 aiai 根手指。
外星人都是很低级的,于是Picks花费了很大的精力,才教会他们学会扳手指数数。
Picks现在准备传递 xx 个脉冲信号给VFleaKing,于是他把信号发给11号外星人,然后11号外星人把信号发送给22号外星人,22号外星人把信号发送给33号外星人,依次类推,最后nn号外星人把信号发给VFleaKing。
但是事情没有Picks想象的那么顺利,由于外星人手指个数有限,所以如果 ii 号外星人收到了 tt 个脉冲信号,他会错误的以为发送过来的是 tmodaitmodai 个脉冲信号,导致只发送了 tmodaitmodai 个脉冲信号出去。
Picks希望他发送出去的脉冲信号数量 xx 与VFleaKing收到的脉冲信号数量 yy 的差的绝对值尽量小。于是他决定通过重新排列这些外星人的顺序来达到这一目的。请你求出与 xx 之差最小的 yy。除此之外,请求出有多少种排列外星人的方式能达到最优解,你只需要输出方案数对 998244353998244353(7×17×223+17×17×223+1,一个质数)取模后的结果。
输入格式
第一行两个正整数n,xn,x。
接下来一行有 nn 个正整数 aiai,表示 ii 号外星人的手指数。
输出格式
第一行一个整数表示最优情况下VFleaKing收到的脉冲数量。
第二行一个整数表示达到最优情况的方案数。
样例一
input
2 15 7 10
output
5 1
explanation
共两种可行方案:
- 15mod7=115mod7=1,1mod10=11mod10=1
- 15mod10=515mod10=5,5mod7=55mod7=5
显然第二种方案更优。
样例二
input
7 33 2 4 6 8 16 16 32
output
1 5040
explanation
每个排列方案都是最优解。
样例三
见样例数据下载
限制与约定
对于每个测试点,答对第一问可获得 40% 的分数,答对第二问可获得 60% 的分数。
请注意你必须输出两个整数否则会判0分。假如你只做了第一问,那么你应该输出你第一问的答案,然后再随便输出一个第二问的答案。
测试点编号 | nn的规模 | xx 和 aiai的规模 |
---|---|---|
1 | n≤10n≤10 | x,ai≤20x,ai≤20 |
2 | n≤50n≤50 | x,ai≤100x,ai≤100 |
3 | ||
4 | n≤100n≤100 | x,ai≤500x,ai≤500 |
5 | ||
6 | ||
7 | n≤1000n≤1000 | x,ai≤5000x,ai≤5000 |
8 | ||
9 | ||
10 |
时间限制:1s1s
空间限制:256MB
f[i][j]代表 处理a[i] 能否得到 j
g[i][j] 记录方案数
考虑取模运算。一个非常基础的性质是:当 x≥ai 时,x mod ai<ai。当 x < ai 时,x mod ai=x 。
那么对于每个ai,要么就把它放在当前位置,现在生效,要么把它放在后面的n−i个位置,使它永不生效,因为如果你先模了一个小于ai的数,再模ai结果是不会变的。
1 #include <cstdio> 2 #include <cctype> 3 #include <algorithm> 4 5 typedef long long LL; 6 7 const int mod=998244353; 8 const int MAXN=1010; 9 const int MAXM=5010; 10 11 int n,s; 12 13 int a[MAXM]; 14 15 bool f[MAXN][MAXM]; 16 17 LL g[MAXN][MAXM]; 18 19 inline bool cmp(int a,int b) {return a>b;} 20 21 inline void read(int&x) { 22 int f=1;register char c=getchar(); 23 for(x=0;!isdigit(c);c=='-'&&(f=-1),c=getchar()); 24 for(;isdigit(c);x=x*10+c-48,c=getchar()); 25 x=x*f; 26 } 27 28 inline void running() { 29 f[0][s]=1;g[0][s]=1; 30 for(int i=1;i<=n;++i) { 31 for(int j=s;j>=0;--j) { 32 f[i][j%a[i]]|=f[i-1][j]; 33 g[i][j%a[i]]=(g[i][j%a[i]]+g[i-1][j])%mod; 34 } 35 if(i!=n) { 36 for(int j=s;j>=0;--j) { 37 f[i][j]|=f[i-1][j]; 38 g[i][j]=(g[i][j]+g[i-1][j]*(n-i))%mod; 39 } 40 } 41 } 42 for(int i=s;i>=0;--i) 43 if(f[n][i]) { 44 printf("%d\n",i); 45 printf("%lld\n",g[n][i]); 46 break; 47 } 48 return; 49 } 50 51 int hh() { 52 read(n);read(s); 53 for(int i=1;i<=n;++i) read(a[i]); 54 std::sort(a+1,a+1+n,cmp); 55 running(); 56 return 0; 57 } 58 59 int sb=hh(); 60 int main(int argc,char**argv) {;}
作者:乌鸦坐飞机
出处:http://www.cnblogs.com/whistle13326/
新的风暴已经出现
怎么能够停止不前
穿越时空 竭尽全力
我会来到你身边
微笑面对危险
梦想成真不会遥远
鼓起勇气 坚定向前
奇迹一定会出现