Problem A: qwb与支教
Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 1520 Solved: 295
[ Submit][ Status][ Web Board]
Description
qwb同时也是是之江学院的志愿者,暑期要前往周边地区支教,为了提高小学生的数学水平。她把小学生排成一排,从左至右从1开始依次往上报数。
玩完一轮后,他发现这个游戏太简单了。于是他选了3个不同的数x,y,z;从1依次往上开始报数,遇到x的倍数、y的倍数或z的倍数就跳过。如果x=2,y=3,z=5;第一名小学生报1,第2名得跳过2、3、4、5、6,报7;第3名得跳过8、9、10,报11。
那么问题来了,请你来计算,第N名学生报的数字是多少?
Input
多组测试数据,处理到文件结束。(测试数据数量<=8000)
每个测试例一行,每行有四个整数x,y,z,N。( 2≤x,y,z≤107,1≤N≤1017)。
Output
Sample Input
2 3 5 2
6 2 4 10000
Sample Output
7
19999
HINT
思路:算是水题把, 只要你会一点点点容斥的东西, 二分+容斥,我也只会 简单容斥...
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
ll x, y, z, n;
ll lcm(ll a, ll b)
{
return a/__gcd(a, b)*b;
}
ll get_cnt(ll a) //这里据说会爆ll, 要用__int128
{
return a - (a/x + a/y + a/z - a/lcm(x, y) - a/lcm(x, z) - a/lcm(y, z) + a/lcm(lcm(x, y), z));
}
int main()
{
while(~scanf("%lld%lld%lld%lld", &x, &y, &z, &n))
{
ll l = 1, r = 9e17 + 5, mid, ans;
while(l <= r)
{
mid = (l+r)/2;
if(get_cnt(mid) >= n)
ans = mid, r = mid - 1;
else l = mid + 1 ;
}
printf("%lld\n", ans);
}
return 0;
}
Problem B: qwb与矩阵
Time Limit: 2 Sec Memory Limit: 128 MBSubmit: 1124 Solved: 227
[ Submit][ Status][ Web Board]
Description
做完了辣么多的数学题,qwb好好睡了一觉。但是他做了一个梦:
有一个n*m的矩阵,qwb在这个矩阵的左上角(1,1),终点在右下角(n,m)。
每个格子中有小钱钱,也可能没有,还有可能是要交过路费的, 并且行走方向必须是靠近终点的方向。往下走一次只能走一格,往右走一次可以走一格也可以走到当前列数的倍数格。
比如当前格子是(x,y),那么可以移动到(x+1,y),(x,y+1)或者(x,y*k),其中k>1。
qwb希望找到一种走法,使得到达右下角时他能够有最多的小钱钱。
你能帮助他吗?
Input
每组测试数据的第一行是两个整数n,m,分别表示行数和列数(1<=n<=20,1<=m<=10000);
接下去给你一个n*m的矩阵,每个格子里有一个数字 k (-100<=k<=100)代表小钱钱的数量。 ∑nm<=3,000,000
Output
Sample Input
1
3 8
9 10 10 10 10 -10 10 10
10 -11 -1 0 2 11 10 -20
-11 -11 10 11 2 10 -10 -10
Sample Output
52
简单的dp。。 暴力转移不会t, 就暴力转移就好了。。
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
using namespace std;
const int maxn = 1e4 + 5;
const int INF = 3e8;
int maze[25][maxn], n, m, dp[25][maxn];
int main()
{
int t;
scanf("%d", &t);
while(t--)
{
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++)
scanf("%d", &maze[i][j]);
for(int i = 0; i <= n; i++)
for(int j = 0; j <= m; j++)
dp[i][j] = -INF;
dp[0][1] = dp[1][0] = 0;
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++)
{
dp[i][j] = max(dp[i-1][j] + maze[i][j], dp[i][j]);
dp[i][j] = max(dp[i][j-1] + maze[i][j], dp[i][j]);
for(int k = 2; k*j <= m; k++) dp[i][k*j] = max(dp[i][j] + maze[i][k*j], dp[i][k*j]);
}
printf("%d\n", dp[n][m]);
}
return 0;
}
Problem C: 勤劳的ACgirls
Time Limit: 1 Sec
Memory Limit: 128 MB
Submit: 151
Solved: 62
[
Submit][
Status][
Web Board]
Submit: 151 Solved: 62
[ Submit][ Status][ Web Board]
Description
为了表示对acmer事业的热爱,队长wc要求每天必须至少要ac掉k题,这m天每天ac掉的题数可以用一个m元组表示。
设不同的m元组一共有c个,请问c的末尾有多少个0?(如果c是0,输出0)
Input
多组测试数据,处理到文件结束。(测试例数量<=160000)
输入的每一行是一个测试例,分别是m、n和k(0<=m,n,k<=1e9),含义如前所述。
Output
Sample Input
3 11 0
3 11 1
999 99999 4
Sample Output
0 0 5
思路:这个题也算比较经典,首先先计算组合数,怎样计算呢?首先隔板法,用隔板让每一块都有k个,然后就是n-m*k小球要插入到n个盒子,可以不放,这就是重复组合的知识了C(n-1,m+n-1);然后就是计算后面有几个0了,你会发现组合数的公式都是阶乘的,这也是经典问题了,看2跟5的数量谁的少。。除法就是上面的数量减去下面的就好了。。相关知识:重复组合
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
ll cal(ll x, ll y) //计算x阶乘里有几个y的方法
{
ll ans = 0;
while(x)
{
ans += x/y;
x /= y;
}
return ans;
}
int main()
{
ll m, n, k;
while(~scanf("%lld%lld%lld", &m, &n, &k))
{
if(m*k > n)
{
puts("0");
continue;
}
ll fz = m-1, fm = n-m*k+m-1;
ll five = cal(fm, 5) - cal(fm-fz, 5) - cal(fz, 5); //组合数除法,相减就好了
ll two = cal(fm, 2) - cal(fm-fz, 2) - cal(fz, 2);
printf("%lld\n", min(two, five));
}
return 0;
}
Problem D: qwb与神奇的序列
Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 1295 Solved: 222
[ Submit][ Status][ Web Board]
Description
qwb又遇到了一道题目:
有一个序列,初始时只有两个数x和y,之后每次操作时,在原序列的任意两个相邻数之间插入这两个数的和,得到新序列。举例说明:
初始:1 2操作1次:1 3 2
操作2次:1 4 3 5 2
……
请问在操作n次之后,得到的序列的所有数之和是多少?
Input
多组测试数据,处理到文件结束(测试例数量<=50000)。
输入为一行三个整数x,y,n,相邻两个数之间用单个空格隔开。(0 <= x <= 1e10, 0 <= y <= 1e10, 1 < n <= 1e10)。
Output
如果和超过1e8,则输出低8位。(前导0不输出,直接理解成%1e8)
Sample Input
1 2 2
Sample Output
15
HINT
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long ll;
const int Mod = 1e8;
ll quick_mul(ll p, ll q)
{
ll ans = 1;
while(q)
{
if(q&1) ans = (ans*p)%(2*Mod);
p = (p*p)%(2*Mod);
q >>= 1;
}
return ans;
}
int main()
{
ll x, y, n;
while(~scanf("%lld%lld%lld", &x, &y, &n))
{
printf("%lld\n", (x+y)%(2*Mod)*(quick_mul(3, n)+1)%(2*Mod)/2%Mod);
}
return 0;
}
Problem F: qwb has a lot of Coins
Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 756 Solved: 248
[ Submit ][ Status ][ Web Board ]
Description
Then comes the question: How many different ways the first player can do that will ensure him win the game?
Input
Output
If the first player can win the game, the method count is the number of different ways that he can do to ensure him win the game, otherwise zero.
Sample Input
3
1 2 3
1
1
Sample Output
0
1
kuangbin博弈题集里的原题..hdu1850
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
const int maxn = 105;
int a[maxn];
int main()
{
int n;
while(~scanf("%d", &n) && n)
{
int sum = 0, ans = 0; //sum初始值为0,因为所有的数字^sum等于它本身
for(int i = 1; i <= n; i++)
scanf("%d" ,&a[i]), sum ^= a[i];
for(int i = 1; i <= n; i++)
if(a[i] > (sum^a[i])) ans++; //注意 ^ 优先级 比 > 小
printf("%d\n", ans);
}
return 0;
}
Problem G: qwb去面试
Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 1789 Solved: 300
[ Submit][ Status][ Web Board]
Description
qwb比较猥琐,借故上厕所偷偷上网求助,聪明的你能帮助他吗?
Input
接下来T行,每行一个正整数n(n<=1e9),意义如题目所述。
Output
Sample Input
2
2
5
Sample Output
2
6
HINT
2=2
5=2+3
思路: 找找规律就知道了, 有3就放3,没3就放2。。。算是个结论把
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
using namespace std;
const int Mod = 1e9 + 7;
typedef long long ll;
ll cal(int x)
{
ll ans = 1, p = 3;
while(x)
{
if(x&1) ans = (ans*p) % Mod;
p = (p*p)%Mod;
x >>= 1;
}
return ans;
}
int main()
{
int t, n;
scanf("%d", &t);
while(t--)
{
scanf("%d", &n);
int k = n / 3;
ll ans = 0;
if(n == 1)
{
printf("1\n");
continue;
}
if(n == 0)
{
printf("0\n");
continue;
}
if(n%3 == 1)
{
ans += cal(k-1);
ans *= (ll)4;
ans %= Mod;
}
else if(n%3 == 2)
ans += (cal(k)*(ll)2)%Mod;
else
ans += cal(k)%Mod;
printf("%lld\n", ans);
}
return 0;
}
Problem K: qwb与小数
Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 451 Solved: 99
[ Submit][ Status][ Web Board]
Description
qwb遇到了一个问题:将分数a/b化为小数后,小数点后第n位的数字是多少?
做了那么多题,我已经不指望你能够帮上他了。。。
Input
多组测试数据,处理到文件结束。(测试数据<=100000组)
每组测试例包含三个整数a,b,n,相邻两个数之间用单个空格隔开,其中0 <= a <1e9,0 < b < 1e9,1 <= n < 1e9。
Output
Sample Input
1 2 1
1 2 2
Sample Output
5
0
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
typedef __int128 ll;
ll a, b, n;
ll quick_mod(ll x, ll t, ll Mod)
{
ll ans = a%Mod; // a一定要mod b
ll ans = 1;
while(t)
{
if(t&1) ans = (ans*x)%Mod;
x = x*x%Mod;
t >>= 1;
}
return ans;
}
int main()
{
while(~scanf("%lld%lld%lld", &a, &b, &n))
{
printf("%lld\n", quick_mod((ll)10, n-1, b)*10/b);
// printf("%lld\n", a*qmod((ll)10, n-1, b)%b*10/b);
// printf("%lld\n", a*quick_mod((ll)10,n,(ll)10*b)/b%10);
}
return 0;
}
Problem J: qwb又偷懒了
Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 697 Solved: 115
[ Submit][ Status][ Web Board]
Description
在接下来长度为n的时间里,每个单位时间都有事情发生,可能会发下以下两种事件:
1)下属递交了一份调查报告,由于太匆忙,上面只有一个整数x,代表一个居民的收入。
2)领导来视察了,领导会来询问,收入在区间[l,r]内的居民的平均收入,qwb需要给出回答。
qwb非常讨厌小数,所以qwb上报时都会省略小数部分。如果上报时统计的人数为0,qwb就暴露了他偷懒的事情,他就会zhizhiwuwu。
Input
多组测试数据,处理到文件末尾。
每组测试数据的第一行为一个正整数n(0<=100000),确保所有的n的和不超过300000
接下来n行,当第一个数为0时,代表操作1,后面跟着一个整数x(0<=x<=1000000),意义如题目所述。
当第一个数为1时,代表操作2,后面跟着两个整数l,r(0<=l<=r<=1000000),意义如题目描述。
Output
每个测试例之后输出一个空行。
Sample Input
3
0 1
0 3
1 1 3
2
0 1
1 2 2
Sample Output
2
zhizhiwuwu
HINT
输入输出包含大规模数据,建议使用scanf,printf.
样例1中,收入为1的居民有一个,收入为3的居民有1个,所以收入在1-3范围内的居民有2个,总收入是4,4/2=2
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 1e6 + 5;
typedef long long ll;
ll num[maxn], sum[maxn];
void update(int x, ll val, int cmd)
{
while(x <= maxn)
{
if(cmd) num[x] += val;
else sum[x] += val;
x += x & -x;
}
}
ll query(int x, int cmd)
{
ll ans = 0;
while(x >= 1)
{
if(cmd) ans += num[x];
else ans += sum[x];
x -= x & -x;
}
return ans;
}
int main()
{
int n, cmd, l, r, x;
while(~scanf("%d", &n))
{
memset(num, 0, sizeof(num));
memset(sum, 0, sizeof(sum));
while(n--)
{
scanf("%d", &cmd);
if(cmd == 0)
{
scanf("%d", &x);
update(x+1, 1, 1); //整体右移
update(x+1, x, 0);
}
else
{
scanf("%d%d", &l, &r);
l++, r++; //整体 右移
if(query(r, 1)-query(l-1, 1) == 0)
printf("zhizhiwuwu\n");
else
printf("%lld\n", (query(r, 0)-query(l-1, 0))/(query(r, 1)-query(l-1, 1)));
}
}
puts("");
}
return 0;
}