JNUOJ 1180 - mod5

题目链接:http://jnuacm.club:8080/oj/problem_show.php?pid=1180

首先,可以自己先一个超时的标程出来:

 1 #include<cstdio>
 2 typedef long long ll;
 3 ll n,m,cnt;
 4 int main()
 5 {
 6     int t;
 7     scanf("%d",&t);
 8     while(t--)
 9     {
10         scanf("%d%d",&n,&m);
11         cnt=0;
12         for(int i=1;i<=n;i++)
13         {
14             for(int j=1;j<=m;j++)
15             {
16                 if((i+j)%5==0) cnt++;
17             }
18         }
19         printf("%lld\n",cnt);
20     }
21 }

那么考虑如何进行时间优化:

这样一来,原本例如(2 + 3)mod 5 = 0 的情况,我们得到的是 ( i_num = 1 ) * ( j_num = 1 ) = 1,1对( i , j ),

现在就可以使 ( i_num = 2 ) * ( j_num = 3 ) = 6,6对( i , j )

因此可以得到一个优化了时间复杂的算法:

 1 #include<cstdio>
 2 #include<cstring>
 3 typedef long long ll;
 4 ll n,m,cnt,i_mod5_equal[5],j_mod5_equal[5];
 5 int main()
 6 {
 7     int t;
 8     scanf("%d",&t);
 9     while(t--)
10     {
11         scanf("%lld%lld",&n,&m);
12
13         cnt=0;
14         for(int i=0;i<=4;i++) i_mod5_equal[i]=0;
15         for(int i=1;i<=n;i++) i_mod5_equal[(i%5)]++;
16
17         for(int j=0;j<=4;j++) j_mod5_equal[j]=0;
18         for(int j=1;j<=m;j++) j_mod5_equal[(j%5)]++;
19
20         for(int i=0;i<=4;i++){
21             for(int j=0;j<=4;j++){
22                 if((i+j)%5==0) cnt+=i_mod5_equal[i]*j_mod5_equal[j];
23             }
24         }
25         printf("%lld\n",cnt);
26     }
27 }

显然,这样一个O(n)的算法,依然比较慢,还可以进一步优化:

 1 #include<cstdio>
 2 #include<cstring>
 3 typedef long long ll;
 4 ll n,m,cnt,i_mod5_equal[5],j_mod5_equal[5];
 5 int main()
 6 {
 7     int t;
 8     scanf("%d",&t);
 9     while(t--)
10     {
11         scanf("%lld%lld",&n,&m);
12
13         cnt=0;
14         for(int i=0;i<=4;i++) i_mod5_equal[i]=n/5;
15         for(int i=1;i<=n%5;i++) i_mod5_equal[i]++;
16
17         for(int j=0;j<=4;j++) j_mod5_equal[j]=m/5;
18         for(int j=1;j<=m%5;j++) j_mod5_equal[j]++;
19
20         for(int i=0;i<=4;i++){
21             for(int j=0;j<=4;j++){
22                 if((i+j)%5==0) cnt+=i_mod5_equal[i]*j_mod5_equal[j];
23             }
24         }
25         printf("%lld\n",cnt);
26     }
27 }

这样就得到了一个O(1)的算法。

两次的时间比较很明显:

时间: 2024-11-13 12:58:17

JNUOJ 1180 - mod5的相关文章

URAL 1180. Stone Game (博弈 + 规律)

1180. Stone Game Time limit: 1.0 second Memory limit: 64 MB Two Nikifors play a funny game. There is a heap of N stones in front of them. Both Nikifors in turns take some stones from the heap. One may take any number of stones with the only condition

任务调度分配题两道 POJ 1973 POJ 1180(斜率优化复习)

POJ 1973 这道题以前做过的.今儿重做一次.由于每个程序员要么做A,要么做B,可以联想到0/1背包(谢谢N巨).这样,可以设状态 dp[i][j]为i个程序员做j个A项目同时,最多可做多少个B项目.枚举最后一个程序员做多少个A项目进行转移(0/1). dp[i][j]=max{dp[i-1][k]+(time-(j-k)*a[i])/b[i]}.于是,二分时间time进行判定即可. #include <iostream> #include <cstdio> #include

1180: 零起点学算法87——超级楼梯(有疑问)

1180: 零起点学算法87--超级楼梯 Time Limit: 1 Sec  Memory Limit: 128 MB   64bit IO Format: %lldSubmitted: 1803  Accepted: 431[Submit][Status][Web Board] Description 有一楼梯共M级,刚开始时你在第一级,若每次只能跨上一级或二级,要走上第M级,共有多少种走法? Input 输入数据首先包含一个整数N,表示测试实例的个数,然后是N行数据,每行包含一个整数M(1

BZOJ 1180: [CROATIAN2009]OTOCI [LCT]

1180: [CROATIAN2009]OTOCI Time Limit: 50 Sec  Memory Limit: 162 MBSubmit: 961  Solved: 594[Submit][Status][Discuss] Description 给出n个结点以及每个点初始时对应的权值wi.起始时点与点之间没有连边.有3类操作: 1.bridge A B:询问结点A与结点B是否连通.如果是则输出“no”.否则输出“yes”,并且在结点A和结点B之间连一条无向边. 2.penguins A

【HDOJ】1180 诡异的楼梯

bfs+优先队列.wa了N次,才发现可以停留等待楼梯变换方向. 1 #include <iostream> 2 #include <queue> 3 #include <cstdio> 4 #include <cstring> 5 using namespace std; 6 7 #define MAXNUM 55 8 9 typedef struct node_st { 10 int x, y, t; 11 node_st() {} 12 node_st(

hdu - 1180 诡异的楼梯 (bfs+优先队列)

http://acm.hdu.edu.cn/showproblem.php?pid=1180 注意点就是楼梯是在harry移动完之后才会改变方向,那么只要统计到达这个点时间奇偶性,就可以知道当前楼梯是水平的还是垂直的. 并且我们需要知道当前到达楼梯这个点的方向,这样才知道下一个往哪个方向走,可以根据dir数组来判断方向. 楼梯不用判重. #include<stdio.h> #include<string.h> #include<queue> #include<io

Vijos 1180 (树形DP+背包)

题目链接: https://vijos.org/p/1180 题目大意:选课.只有根课选了才能选子课,给定选课数m, 问最大学分多少. 解题思路: 树形背包.cost=1. 且有个虚根0,取这个虚根也要cost,所以最后的结果是dp[0][m+1]. 本题是cost=1的特殊背包问题,在两个for循环上有一个优化. for(f+1...j....cost) for(1....k...j-cost) 其中f为当前已经dfs子结点个数.之所以+1,是因为根要预留一个空间. f+=dfs(t),dfs

HDU 1180 诡异的楼梯 (搜索)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1180 TLE n次.. 注意两点:1,S.T这三种位置是可以停留一秒的.即在没有路可走的时候可以停留一秒. 2, bfs宽搜应该使用优先队列, 并且vis标记加在将next节点push到队列中的时候. 然后就是奇偶判断什么的就可以了. 代码: 1 #define _CRT_SECURE_NO_WARNINGS 2 #include <functional> 3 #include <algor

HDU 1180 (BFS搜索)

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1180 题目大意:迷宫中有一堆楼梯,楼梯横竖变化.这些楼梯在奇数时间会变成相反状态,通过楼梯会顺便到达前进方向的下一个点(跳过楼梯). 同时可以在原地等待,问到达终点的最少时间. 解题思路: 很有趣的一个题. 还是先BFS,对于一个楼梯,change函数负责计算出走楼梯能够到达的新的X和Y,再判一次是否越界或不可达. 注意,在'.'点是可以原地等待的,需要额外Push这个点,这也是这题不会出现走不出