拐咯拐咯,又是被爆揍的一天
目录
7-2 How long could we be a sad song
注意:上述例子中,当剩下 23333 和 543589 时,如果 mz 选择了乘法,最终得数将变成奇数,他将失去胜利,因此为了自己能够获得胜利,mz 一定会选择加法。
7-1 Enchanted
众所周知,7 月 7 号 Taylor Swift 发布了 《SPEAK NOW》(Taylor’s Version),kk 作为一个霉粉,他现在想托朋友为他买一张实体CD,而他的朋友没有那么轻易的就答应他,而是给了他一个问题,只有当 kk 解决掉这个问题之后才能获得实体CD。但是呢,kk 现在没有空去解决这个问题,那么,善良的你一定会帮他解决这个问题并帮助他拿到他心爱的专辑的吧!!
这个问题是这样的, kk 有 n 堆钞票,其中每堆钞票的钞票数量为 Si,我们记第 i 堆中的第 j 张钞票的价值为 ai,j。现在 kk 有一个总乘积 x。我们需要从每堆里选出一张钞票,请问一共有多少种方案,使得这些钞票的价值乘积恰好为 x。
注意:当选择的钞票价值相同,但编号不同时,我们认为是不同的方案。例如,某一堆的两个相同价值的球被记为两种方案。
提示:可以从数据范围以及累乘符号入手。输入格式:
第一行输入两个正整数 n(2≤n) 和 x(1≤x≤1018)。分别代表钞票堆数和总乘积。注意:数据保证每堆钞票数量的乘积最多为 105:∏i=1nSi≤105。
接下来 n 行,每行先输入一个整数 Si(2≤Si)。代表第 i 堆钞票数量。再输入 Si 个 整数 ai,j(1≤ai,j≤109,1≤j≤Si)。代表每张钞票的价值,某堆可能会出现相同价值钞票。
输出格式:
输出方案数
输入样例 1:
2 40 3 1 8 4 2 10 5
输出样例 1:
2
样例解释 1:
对于样例 1,当在第 1 堆中选择钞票 3 和 第 2 堆中选择钞票 1 时,我们有 a1,3×a2,1=4×10=40。当在第 1 堆中选择钞票 2 和 第 2 堆中选择钞票 2 时,我们有 a1,2×a2,2=8×5=40。没有其他方法可以使乘积为 40,所以答案是 2。
输入样例 2:
3 200 3 10 10 10 3 10 10 10 5 2 2 2 2 2
输出样例 2:
45
样例解释 2:
对于样例 2,请注意,我们区分所有钞票,即使它们有相同的价值。
输入样例 3:
3 1000000000000000000 2 1000000000 1000000000 2 1000000000 1000000000 2 1000000000 1000000000
输出样例 3:
0
样例解释 3:
对于样例 3,没有方法使乘积为 x。
一个dfs的题趴,赛时答案错误,写的是乘法没有考虑到爆longlong的情况
除法版本
#include <bits/stdc++.h>
using namespace std;
#define ll long long
ll x;
vector<ll>v[100005];
ll cnt;
int n;
void dfs(ll a, ll c) {//a表示层数,c表示被除数
if (a == n) {//当到最后一层时
if (c == 1) {//如果被除数等于1,表示找到一种方案数
cnt++;
}
return;
}
for (int i = 0; i < v[a].size(); i++) {
ll t = v[a][i];
if(c%t==0){//判断是否整除
dfs(a + 1, c /t);
}
}
}
int main() {
cin >> n >> x;
for (int i = 0; i < n; i++) {
ll q;
cin >> q;
while (q--) {
ll p;
cin >> p;
v[i].push_back(p);
}
}
dfs(0, x);
cout << cnt<<"\n";
return 0;
}
乘法版本
#include <bits/stdc++.h>
using namespace std;
#define ll long long
ll x;
vector<ll>v[100005];
ll cnt;
int n;
void dfs(ll a, ll c) {//a表示层数,c表示乘数
if (a == n) {//到最后一层
if (c == x) {//正好等于x时,表示找到一个合理的方案数
cnt++;
}
return;
}
for (int i = 0; i < v[a].size(); i++) {
ll t = v[a][i];
if (x/t>=c&&x%t==0) {//判断是否整除和是否会爆longlong
dfs(a + 1, c * t);
}
}
}
int main() {
cin >> n >> x;
for (int i = 0; i < n; i++) {
ll q;
cin >> q;
while (q--) {
ll p;
cin >> p;
v[i].push_back(p);
}
}
dfs(0, 1);
cout << cnt<<"\n";
return 0;
}
7-2 How long could we be a sad song
5 月 26 号 Taylor 正式发售 《Midnights》 的深夜豪华版(The Late Night Version),其中包含了一首 CD 独占曲 You’re Losing Me,kk 听的非常上头,于是边听边跟 mz 玩起了小游戏。
这个游戏是这个亚子的,他们会拿出 n 张卡牌,然后在每张卡牌上用铅笔写上一个正整数。
游戏由 kk 先手操作。对于每次操作:
- 1.若当前只剩下一张卡牌时,游戏结束,卡牌上的数字为偶数则 mz 获胜,否则 kk 获胜。
- 2.若当前剩余两张牌及以上,则当前玩家可以任选两张卡牌,假设这两张牌的值为 a,b,当前玩家可以对这两张牌选择乘法或者加法得到一个新的值 c,然后将其中一张卡牌丢掉,另一张卡牌的原数字擦掉并改写为 c 放入卡牌堆。
现在假设双方 均以最优策略(大家都尽自己最大的努力去获得胜利) 操作,最后谁会赢?
输入格式:
第一行输入一个整数 n(1≤n≤106),代表最初的卡牌数。
第二行输入 n 个整数 ai(1≤ai≤109),代表卡牌的值。输出格式:
游戏结束,卡牌上的数字为偶数则输出 mz nb,否则输出 kk caiji。
输入样例 1:
3 233 2333 23333
输出样例 1:
mz nb
样例 1 解释:第一轮 kk 先选 233 和 2333 做乘法,得到 543589;此时牌堆剩下 23333 和 543589,第二轮轮到 mz 操作,他选择将剩下两个数做加法,则得到 566922 为偶数;此时牌堆剩下 566922,第三轮轮到 kk 操作,牌堆只剩一张牌,因此游戏结束,最后一张牌为偶数,mz 胜利。上述所描述的只是其中一种方案,其他的方案大家可以自行尝试。但无论怎样选择操作,无论 kk 如何努力,mz 都能将最后一个数变成偶数。
注意:上述例子中,当剩下 23333 和 543589 时,如果 mz 选择了乘法,最终得数将变成奇数,他将失去胜利,因此为了自己能够获得胜利,mz 一定会选择加法。
输入样例 2:
4 1 1 1 1
输出样例 2:
kk caiji
就是这个又熟悉又猛wa的题搞烂了我的心态,小菜是这样的
#include <bits/stdc++.h>
using namespace std;
#define ll long long
ll n;
ll cnt;
int main() {
cin>>n;
for(int i=0;i<n;i++){
ll x;
cin>>x;
if(x%2!=0)cnt++;//记录奇数的个数
}
if(n==1||n==2){//如果n==1||n==2时,只要出现过奇数,kk赢,反之mz赢
if(cnt)cout<<"kk caiji\n";
else cout<<"mz nb\n";
}
else if(n%2==0){//对于偶数,只有当奇数个数超过n-2时kk才能赢,反之mz赢
if(cnt>=n-2)cout<<"kk caiji\n";
else cout<<"mz nb\n";
}
else{//奇数mz赢
cout<<"mz nb\n";
}
return 0;
}
7-3 Amazing News
好消息,好消息,7月14-7月16薛之谦!他来衡阳开演唱会啦!!!!!!!!mq想拜托他的朋友帮他抢到一张物美价廉的原价外场票,然而他的朋友正忙着解决一个大问题没有时间帮mq抢票。如果mq帮助朋友解决了这个问题就可以获得老薛的演唱会门票,但是mq又解决不了这个问题,那么善良的你一定会帮助mq解决问题助他拿到演唱会门票的吧!!!一定会的吧/(ㄒoㄒ)/~~
在演唱会中由于每个人有各自的座位,演唱会的入口大小只能让一个人通过,朋友便想通过让观众排队的方式让他们有序入场,提高进场效率
一共有N个人购买了演唱会门票,每个人有个编号:1,2,3…N
每个座位只能坐一个人
编号不等同座位号,每个人的座位号只有朋友通过后台数据才知道
朋友已经提前计算好了每个人在队伍中的位置,你只需要跟着朋友的指示将最后的队伍输出就可以了:
1 x y
: 将y排到x的后面
需要遵守以下约定
x=y;
在本次操作之前没有任何人排在x后面;
在本次操作之前没有任何人排在y前面;
在本次操作之前,x和y在不同的队伍中;
2 x y
: 将x,y断开
需要遵守以下约定
x=y;
在本次操作之前y正好排在x的后面;
3 x
: 按顺序从头到尾打印出x所在的队伍目前的排队情况(题目不特指薛之谦演唱会,情节纯属虚构,如有雷同纯属巧合)
输入格式:
第一行输入两个整数:人数N,朋友所需操作数Q
接下来Q行每行输入2到3个数,第一个数为操作pi,后面的1或2个数为人员x,y输出格式:
如果pi=3,输出一行第一位数字为该队伍目前的人数,后面j1,j2,j3…jm表示该队伍人员
数据范围:
2≤N≤105
1≤Q≤105
1≤x≤N
1≤y≤N
所有输入都是正整数
所有的操作都符合条件
所有打印的最大长度不会超过106
输入样例:
在这里给出一组输入。例如:
7 14 1 6 3 1 4 1 1 5 2 1 2 7 1 3 5 3 2 3 4 3 6 2 3 5 2 4 1 1 1 5 3 2 3 4 3 6
输出样例:
在这里给出相应的输出。例如:
5 6 3 5 2 7 2 4 1 5 6 3 5 2 7 4 1 5 2 7 1 4 2 6 3
链表题,按题意模拟即可
#include <bits/stdc++.h>
using namespace std;
int n, q, cnt;
int a[100005];//前面的
int b[100005];//后面的
int c[100005];
int main() {
cin >> n >> q;
while (q--) {
int p;
cin >> p;
if (p == 1) {
int x, y;
cin >> x >> y;
a[y] = x;//y前标记为x
b[x] = y;//x后标记为y
}
else if (p == 2) {
int x, y;
cin >> x >> y;
a[y] = 0;//断开则归0
b[x] = 0;//断开则归0
}
else {
int x;
cin >> x;
while (a[x] != 0) {//往前找到链表首元素
x = a[x];
}
cnt = 0;
while (b[x] != 0) {//往后找到链表末尾元素
c[cnt++] = x;
x = b[x];
}
c[cnt++]=x;
cout << cnt << " ";//按要求输出
for (int i = 0; i < cnt; i++) {
cout << c[i];
if(i!=cnt-1)cout<< ' ';
}
cout << "\n";
}
}
return 0;
}
7-4 Counter-diagonal
给定一个 n∗n 的方阵,行和列的下标均从 0 开始 ,该方阵仅由数字组成。而你的任务是求出方阵中 x,y 位置上所对应的数字,其中 x 代表行,y 代表列。
下图所示分别为一个 3∗3 的方阵,和一个 5∗5 的方阵,请根据该方阵的规律推出其他大小方阵排列规律。
输入格式:
输入三个整数 n(1≤n≤109+1),x(0≤x≤109),y(0≤y≤109)
输出格式:
输出该位置对应的数值。
输入样例 1:
3 2 1
输出样例 1:
7
输入样例 2:
5 2 2
输出样例 2:
12
手推公式题,找规律
#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll n,x,y;
int main(){
cin>>n>>x>>y;
// n=3;
// for(int x=0;x<n;x++){
// for(int y=0;y<n;y++){
ll ans=((x+2)*(x+1)/2-1);//对应的列的首行元素
if(y<n-x){//如果y小于这个范围
ans+=y*(x+1)+(y*(y-1))/2;//当前列是从x+1一直加到y的公差为1的等差数列
}
else{//反之
ans+=((n-1)-x)*(x+1)+((n-1)-x)*((n-1)-x-1)/2;
//前面是当前列从x+1到(n-1)的公差为1的等差数列
int t=y-((n-1)-x);//剩下的行数
ans+=t*(n-1)-t*(t-1)/2;//遵循从(n-1)开始公差为-1的等差公式
}
cout<<ans;
// cout<<' ';
// }cout<<"\n";
// }
return 0;
}
7-5 扭转乾坤
题解
自己比划一下可以发现轨迹是一条直线,长度为 4∗n∗d,唯一的坑点是注意爆 longlong。
本题为判题方式为 Special Judge
你现在有两个圆环,其中小圆环的直径为 d,大圆环的直径是 2d。你将小圆环防在大圆环内,并让小圆环紧贴大圆环内壁进行无滑动的滚动。
你总是喜欢动态的美,你在小圆环上等间隔地标记了 n 个点,你想知道在小圆环贴着大圆环运动一周后,你所标记的 n 个点所经过的轨迹的长度之和是多少。
输入格式:
输入包含一行,两个整数 n,d(1≤n,d≤109)。
输出格式:
输出包含一行一个浮点数,表示 n 个点所经过的轨迹的长度之和,所输出的答案和标准答案的绝对误差或相对误差在 10−6 范围内会被认为是正确的。
输入样例:
1 1
输出样例:
4.00000000
这个题确实不知道为啥,盲猜了一发4nd过了
#include <bits/stdc++.h>
using namespace std;
#define ll long long
const double PI=3.141592635;
int main() {
ll n,d;
cin>>n>>d;
printf("%.8f",4*n*d*1.0);
return 0;
}
7-6 分冰棍
衡阳太热啦,mq为了避暑进货一大批冰棍,现在mq决定让大家帮忙分冰棍,并把冰棍奖励给榜一
现在一共有N根冰棍和M个人,你需要把冰棍分给每个人,并且使每个人所分到的冰棍数都不一样(没有任何两个人的冰棍数是一样的)如果可以这样分输出"possible",否则输出"impossible"。
输入格式:
第一行一个正整数T
接下来T行每行两个数字N,M表示冰棍数和人数;
输出格式:
共T行每行输出"possible"或者"impossible"。
数据范围:
- 1≤T≤5
- 1≤N≤1000000
- 1≤M≤1000
输入样例:
在这里给出一组输入。例如:
3 9 3 12 1 9 4
输出样例:
在这里给出相应的输出。例如:
possible possible impossible
题目等价于判断首项为1,公差为1的等差公式和冰棍数的大小,一开始把公式整错了尬住
#include <bits/stdc++.h>
using namespace std;
int main() {
int t;
cin>>t;
while(t--){
int n,m;
cin>>n>>m;
if(m*(m+1)/2<=n){
cout<<"possible\n";
}
else cout<<"impossible\n";
}
return 0;
}