125 条题解
-
0gsrq LV 10 @ 2009-10-18 11:25:04
Orz 340508965
转一下
var
a,i,k,n:longint;
sum:int64;
b:array[0..100000] of longint; //表示余数为j时sum的总个数
begin
readln(n,k);
sum:=0;
for i:=1 to n do
begin
readln(a);
inc(sum,a);
inc(b[sum mod k]); //更新相应的b[]
end;
sum:=b[0]; //刚才说的注意的地方
for i:=0 to k-1 do
sum:=(sum+(b[i]*(b[i]-1))shr 1) mod 1234567;
writeln(sum);
end.编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms
├ 测试数据 10:答案正确... 0ms
---|---|---|---|---|---|---|---|-
Accepted 有效得分:100 有效耗时:0ms噢耶 (^o^)/ 秒杀 呵呵很难得啊
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|--
先说说怎么做吧SUM[i]是代表前i个数的和
当(SUM[i]-SUM[j]) MOD k=0 这时[j+1,i]就是满足的一个区间 一个方案了
而我们求的是(SUM[i]-SUM[j]) MOD k=0 这样的方案总个数
我们又可以推出 上式等价于SUM[i] MOD k=SUM[j] MOD k
所以我们就是求SUM[i] MOD k=SUM[j] MOD k 的方案个数了假设 sum[i],sum[j],..sum[k](共bn个) 都是 MOD k 余数为k-1的sum
那么从上面bn个sum中任意选取两个就能得出(SUM[i]-SUM[j]) MOD k=0
那么在bn个sum中怎么配对呢(下面的sum[bn]表示上述bn个sum中的第n个sum)
很简单 先是sum[b1]与sum[b2] sum[b3] ...sum[bn] (bn-1 个)
然后sum[b2]与sum[b3] sum[b4] ...sum[bn] (bn-2 个)
然后sum[b3]与sum[b4] sum[b5] ...sum[bn] (bn-3 个)
............
最后sum[bn-1]与sum[bn] ( 1 个)方案总数=n-1+n-2+n-3+...+1=bn*(bn-1) div 2
(好像这是初中的知识吧? 可是当时我看楼下的楼下的楼下....的题解 我一时竟然还不明白为什么)所以 当sum mod k的余数为k-1时有bn*(bn-1) div 2个方案总数了
就这样依次得出余数为k-1 k-2 k-3 ...0的时候方案总数 再相加一下得出答案所以在读入一个数的时候就计算sum然后计算sum mod k 的余数
而b[j]表示余数为j的sum个数 此时根据上面新得出的更新相应的b[j]这样在读入完毕之后就可以根据b[j]直接计算总方案数了
特别值得注意的是!!!!
计算余数为0的方案总数时候还要加上b[0] 也就是b[0]*(b[0]-1) div 2+b[0]
为什么?? 因为余数为0的时候单独一个sum[i]就能成为一个方案了还有比如div 2可以用shr 1 这样可以加快速度
呼呼(~ o ~)~zZ 说得好累啊
我自己都快被讲糊涂了 呵呵
希望有不懂这道题目的人能看懂....
这样就不算白忙了 -
02009-10-14 21:16:37@
感谢340508965的妙解,犹如醍醐灌顶啊。
-
02009-10-12 16:02:38@
var l,n,k:longint;
a,b:array[0..100000]of longint;
procedure init;
var i,j,q,r,t,all:longint;
begin
readln(n,k);
fillchar(a,sizeof(a),0);
r:=0;
all:=0;
for i:=1 to n do
begin
readln(q);
all:=all+q;
if all>=k then all:=all mod k;
r:=r+a[all];
if all=0 then inc(r);
if r>=1234567 then r:=r mod 1234567;
inc(a[all]);
end;
writeln(r);
end;
begin
init;
end. -
02009-10-10 19:40:28@
开始把题意看错,以为是DP,看了数据范围后郁闷了半天......
后来看题解才发现题意理解错了.....
倒............
搜一遍即得,在大脑中想想数格子的场景吧.....
---|---|---|---|---|---|---|---|---|---|---|-
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms
├ 测试数据 10:答案正确... 0ms
---|---|---|---|---|---|---|---|-
Accepted 有效得分:100 有效耗时:0ms
按Ctrl+A看代码
var l,n,k:longint; a,b:array[0..100000]of longint;procedure init; var i,j,q,r,t,all:longint;begin readln(n,k); fillchar(a,sizeof(a),0); r:=0; all:=0; for i:=1 to n do begin readln(q); all:=all+q; if all>=k then all:=all mod k; r:=r+a[all]; if all=0 then inc(r); if r>=1234567 then r:=r mod 1234567; inc(a[all]); end; writeln(r);end;begin init;end. -
02009-09-23 10:03:15@
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 56ms
├ 测试数据 10:答案正确... 166ms
---|---|---|---|---|---|---|---|-
Accepted 有效得分:100 有效耗时:222ms简简单单
-
02009-09-13 14:10:49@
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 41ms
├ 测试数据 10:答案正确... 181ms只用加法就够了 简单
-
02009-09-12 21:38:48@
赞340508965的题解
要不然我还真不知道该怎么做最近vijos超慢,用世界之窗浏览器根本打不开页面,现在只能用Opera
-
02009-09-10 16:31:21@
意想不到的好方法…………
偶然在…………膜拜ing
———————————————————————成长中的菜鸟 -
02009-08-30 20:19:23@
...竟然没想到桶排。。直接快排一个。。然后就耗时了。。无语了。。
-
02009-08-17 10:53:04@
好方法 ~
-
02009-08-14 21:05:07@
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms
├ 测试数据 10:答案正确... 0ms
---|---|---|---|---|---|---|---|-
Accepted 有效得分:100 有效耗时:0ms(^o^)/ 20行 MS
-
02009-08-13 11:09:05@
AC 100纪念~~~~
-
02009-08-12 20:23:55@
囧。看错数据范围了。开了10000的数组,少了个0,RE了3个点。
-
02009-08-11 16:33:30@
十分感谢340508965的题解!
-
02009-08-08 10:42:36@
竟然没秒!10ms汗死...........
-
02009-08-04 14:53:44@
余数为0的时候单独一个sum[i]就可以构成一个方案了。
所以余数为0时cn1+cn2
余数不为0时cn2
答案就是求和 -
02009-08-03 21:43:39@
如果您在程序中使用了iostream;
请改为stdio.h -
02009-08-03 21:20:39@
谢谢楼下的楼下
^ ^ -
02009-07-27 15:40:57@
var n,k,i,v:longint;
d:array[0..100000] of longint;
total,sum:int64;
begin readln(n,k);
sum:=0;
fillchar(d,sizeof(d),0);
for i:=1 to n do
begin
readln(v);
sum:=sum+v;
inc(d[sum mod k]);
end;
for i:=1 to k-1 do
total:=(total+d[i]*(d[i]-1)div 2) mod 1234567;
total:=(total+d[0]+d[0]*(d[0]-1) div 2) mod 1234567;
writeln(total);
end.
大家注意了,读入的时候千万往不要用数组 不然只有80分 最后2个点存取非法 216感谢楼下的妙解``
-
02009-07-24 16:29:24@
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
├ 测试数据 06:答案正确... 0ms
├ 测试数据 07:答案正确... 0ms
├ 测试数据 08:答案正确... 0ms
├ 测试数据 09:答案正确... 0ms
├ 测试数据 10:答案正确... 0ms
---|---|---|---|---|---|---|---|-
Accepted 有效得分:100 有效耗时:0ms噢耶 (^o^)/ 秒杀 呵呵很难得啊
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|--
先说说怎么做吧SUM[i]是代表前i个数的和
当(SUM[i]-SUM[j]) MOD k=0 这时[j+1,i]就是满足的一个区间 一个方案了
而我们求的是(SUM[i]-SUM[j]) MOD k=0 这样的方案总个数
我们又可以推出 上式等价于SUM[i] MOD k=SUM[j] MOD k
所以我们就是求SUM[i] MOD k=SUM[j] MOD k 的方案个数了假设 sum[i],sum[j],..sum[k](共bn个) 都是 MOD k 余数为k-1的sum
那么从上面bn个sum中任意选取两个就能得出(SUM[i]-SUM[j]) MOD k=0
那么在bn个sum中怎么配对呢(下面的sum[bn]表示上述bn个sum中的第n个sum)
很简单 先是sum[b1]与sum[b2] sum[b3] ...sum[bn] (bn-1 个)
然后sum[b2]与sum[b3] sum[b4] ...sum[bn] (bn-2 个)
然后sum[b3]与sum[b4] sum[b5] ...sum[bn] (bn-3 个)
............
最后sum[bn-1]与sum[bn] ( 1 个)方案总数=n-1+n-2+n-3+...+1=bn*(bn-1) div 2
(好像这是初中的知识吧? 可是当时我看楼下的楼下的楼下....的题解 我一时竟然还不明白为什么)所以 当sum mod k的余数为k-1时有bn*(bn-1) div 2个方案总数了
就这样依次得出余数为k-1 k-2 k-3 ...0的时候方案总数 再相加一下得出答案所以在读入一个数的时候就计算sum然后计算sum mod k 的余数
而b[j]表示余数为j的sum个数 此时根据上面新得出的更新相应的b[j]这样在读入完毕之后就可以根据b[j]直接计算总方案数了
特别值得注意的是!!!!
计算余数为0的方案总数时候还要加上b[0] 也就是b[0]*(b[0]-1) div 2+b[0]
为什么?? 因为余数为0的时候单独一个sum[i]就能成为一个方案了还有比如div 2可以用shr 1 这样可以加快速度
呼呼(~ o ~)~zZ 说得好累啊
我自己都快被讲糊涂了 呵呵
希望有不懂这道题目的人能看懂....
这样就不算白忙了---|---|---|---|---|---|---|---|---|--晒程序了---|---|---|---|---|---|---|---|---|--
var a,i,k,n:longint;
sum:int64;
b:array[0..100000] of longint; //表示余数为j时sum的总个数
begin
readln(n,k); sum:=0;
for i:=1 to n do
begin
readln(a); inc(sum,a);
inc(b[sum mod k]); //更新相应的b[]
end;sum:=b[0]; //刚才说的注意的地方
for i:=0 to k-1 do
sum:=(sum+(b[i]*(b[i]-1))shr 1) mod 1234567;
writeln(sum);
end.