Ural 1760 Infernal Work

来源:互联网 发布:pop3端口是多少 编辑:程序博客网 时间:2024/05/21 01:52

    链接:Ural - 1760

    题意:这道题题意很难理解,大体的意思是给三个数, a, b, n, 有两个人,第一个人把这 n 个数按顺序写在一页页纸上,每页纸写 a 个数,第二个人每页纸写 b 个数,然后要求判断有多少对数(x,y),x 和 y 对于第一个人来说是在同一页纸上的,但对于第二个人来说是在不同页上的。


    思路:设第一个人的每一页第一个数为 i ,i 在第二个人的页数为 x,那么从 A(第一个人)每一页的第二个数开始找,找到第一个和 i 在 B(第二个人)中不同页的数 d,此时,d 对于它所在的 A的那一页在它前面的数,能形成的对数就是(d-i),也就是 d 在该页的偏移量,因为在该页 d 前面的数都是符合它们在 A同页,在 B不同页。接着往下找,如果目前的数 j 依然和前面的 d 在同一页,那么j 与该页前面能形成的对数也和 d 一样,如果 j 再变成 d 所在页的下一页,那么此时对于它来说,在 A的该页前面的数都能和它形成对,所以对数是它自己的偏离量,也等于 d 的偏移量加上 (j-d)。以此类推,把所有的对数加起来就是答案。因为数据比较大,所以答案要用 long long 来存。

 

    前面解释得比较抽象,不妨看看例子吧。

 

    首先看 a = 3,b = 4,n =10,在 A的第一页开始找,但这一页每个数在 A 中同页,在 B 中也同页,所以第一页没有。第二页中,4 在B 的第一页,5在B的第二页,所以 5 是第一个和该页第一个数在 B 中不同页的数,偏移量为 1,所以形成的对数为 1,接下来 6,6和 5 在 B 中保持同页,所以对数也是 4  的偏移量 1,然后看 8 ,8 和 7 在 B 中同页。看 9 ,9 是该页中第一个和该页第一个数在 B 中不同页的数,偏移量是 2,所以对数为 2。最后 10,只有一个数,没有。所以答案为 1 + 1 + 2 = 4.

 

1    4   7    10                1    5   9

2    5   8                         2    6   10

3    6   9                         3    7  

                                       4    8

   (A)                             (B)

 

 

    再看一个例子, a = 5,b =2,n= 10, A中第一页从 2 开始找,2 和1 同页,继续。3 和 1不同页,对数为它的偏移量 2, 然后 4 和 3 同页,所以对数也是 2,而 5 和4 不同页,所以对数也它自己的偏移量 4. 第二页的 7 对数1,8 对数 1,9 对数3,10 对数 3.最终答案为 16.

 

1    6                        1   3  5   7   9

2    7                         2   4  6   8   10

3    8                               (B)

4    9

5    10

  (A)

 

    算法步骤:

    步骤1:ans 保存答案,可以形成多少对数,a, b, n意义和题目相同,开始循环,i 从 0 开始,每次 +a ,所以每次 i都是 A 每页的第一个数,pos 表示 i在B 中的页数,k 代表目前应该加上的偏移量,flag 代表是否找到第一个和 i 不同页的数,cur 代表当前数的前面的数所处页数,用于判断是否出现在 B 中转移到下一页。

    步骤2:对于每个 i,让 j 从 i+1 开始,直到 i+a结束,找遍该页中的数,如果该数 j 和 i 在B 中处在同一页,则 continue, 否则,判断是否是第一个和 i 不同页的数,是的话更新 cur 为 J 所处页数, k 为偏移量,flag 改变。已经不是第一个数了,则判断是否在 B 中跳转到新的一页,是则更新 k 和 cur。ans 加上符合条件的对数。

    步骤3:输出 ans。


#include <iostream>#include <cstring>#include <algorithm>using namespace std;int a,b,n;int main(){long long ans;while(cin>>a>>b>>n){ans = 0;for(int i = 0;i < n;i += a){int pos = i/b,k = 1,cur;  // 整除以 b 就是该数所处页数bool flag = 0;for(int j = i+1;j < i+a && j < n;++j){int p2 = j/b; if(p2 == pos) continue;if(!flag){cur = p2;k = j -i;flag = 1;}if(p2 != cur){k = j - i;cur = p2;}ans += k;}}cout<<ans<<endl;}}


0 0
原创粉丝点击