生活大爆炸版石头剪刀布
题目描述
石头剪刀布是常见的猜拳游戏:石头胜剪刀,剪刀胜布,布胜石头。如果两个人出拳一样,则不分胜负。在《生活大爆炸》第二季第8 集中出现了一种石头剪刀布的升级版游戏。
升级版游戏在传统的石头剪刀布游戏的基础上,增加了两个新手势:
斯波克:《星际迷航》主角之一。
蜥蜴人:《星际迷航》中的反面角色。
这五种手势的胜负关系如表一所示,表中列出的是甲对乙的游戏结果。
现在,小A 和小B 尝试玩这种升级版的猜拳游戏。已知他们的出拳都是有周期性规律的,但周期长度不一定相等。例如:如果小 A以“石头 - 布- 石头- 剪刀- 蜥蜴人- 斯波克”长度为6 的周期出拳,那么他的出拳序列就是“石头- 布- 石头- 剪刀- 蜥蜴人- 斯波克- 石头- 布- 石头- 剪刀- 蜥蜴人- 斯波克- ……”,而如果小B 以“剪刀- 石头- 布- 斯波克- 蜥蜴人”长度为5 的周期出拳,那么他出拳的序列就是“剪刀- 石头- 布- 斯波克- 蜥蜴人- 剪刀- 石头- 布-斯波克- 蜥蜴人- ……”
已知小A 和小B 一共进行N 次猜拳。每一次赢的人得1 分,输的得0 分;平局两人都得0 分。现请你统计N 次猜拳结束之后两人的得分。
输入输出格式
输入格式:
输入文件名为rps.in。
第一行包含三个整数:N ,NA,NB,分别表示共进行 N 次猜拳、小 A 出拳的周期长度,小B 出拳的周期长度。数与数之间以一个空格分隔。
第二行包含NA个整数,表示小 A 出拳的规律,第三行包含NB个整数,表示小 B 出拳的规律。其中,0 表示“剪刀”,1 表示“石头”,2 表示“布”,3 表示“蜥蜴人”, 4 表示“斯波克”。数与数之间以一个空格分隔。
输出格式:
输出文件名为**rps.out **。
输出一行, 包含两个整数,以一个空格分隔,分别表示小A 、小B 的得分。
输入输出样例
输入样例#1:
10 5 6
0 1 2 3 4
0 3 4 2 1 0
输出样例#1:
6 2
输入样例#2:
9 5 5
0 1 2 3 4
1 0 3 2 4
输出样例#2:
4 4
说明
对于100%的数据,0 < N ≤ 200 ,0 < NA ≤ 200 , 0 < NB ≤ 200 。
思路
用数组存下不同情况的贡献(见代码)
然后对每一个情况判断
代码
#include<cstdio>
using namespace std;
int n,na,nb,sa,sb,a[190],b[190],f[5][5];
void work()
{
for(int i=na;i<n;i++) a[i]=a[i%na];
for(int i=nb;i<n;i++) b[i]=b[i%nb];
f[0][2]=1,f[0][3]=1;
f[1][0]=1,f[1][3]=1;
f[2][1]=1,f[2][4]=1;
f[3][2]=1,f[3][4]=1;
f[4][0]=1,f[4][1]=1;
}
void Input() //输入
{
scanf("%d%d%d",&n,&na,&nb);
for(int i=0;i<na;i++) scanf("%d",&a[i]);
for(int i=0;i<nb;i++) scanf("%d",&b[i]);
}
int main()
{
Input();
work();
for(int i=0;i<n;i++)
sa+=f[a[i]][b[i]],sb+=f[b[i]][a[i]];
printf("%d %d\n",sa,sb);
return 0;
}
无线网络发射器选址
题目描述
随着智能手机的日益普及,人们对无线网的需求日益增大。某城市决定对城市内的公共场所覆盖无线网。
假设该城市的布局为由严格平行的129 条东西向街道和129 条南北向街道所形成的网格状,并且相邻的平行街道之间的距离都是恒定值 1 。东西向街道从北到南依次编号为0,1,2…128 , 南北向街道从西到东依次编号为0,1,2…128 。
东西向街道和南北向街道相交形成路口,规定编号为x 的南北向街道和编号为y 的东西向街道形成的路口的坐标是(x , y )。 在 某 些 路口存在一定数量的公共场所 。
由于政府财政问题,只能安装一个大型无线网络发射器。该无线网络发射器的传播范围
一个以该点为中心,边长为2*d 的正方形。传播范围包括正方形边界。
例如下图是一个d = 1 的无线网络发射器的覆盖范围示意图。
现在政府有关部门准备安装一个传播参数为d 的无线网络发射器,希望你帮助他们在城市内找出合适的安装地点,使得覆盖的公共场所最多。
输入输出格式
输入格式:
输入文件名为wireless.in。
第一行包含一个整数d ,表示无线网络发射器的传播距离。
第二行包含一个整数n ,表示有公共场所的路口数目。
接下来n 行,每行给出三个整数x , y , k , 中间用一个空格隔开,分别代表路口的坐标( x , y )
以及该路口公共场所的数量。同一坐标只会给出一次。
输出格式:
输出文件名为wireless.out 。
输出一行,包含两个整数,用一个空格隔开,分别表示能覆盖最多公共场所的安装地点 方案数,以及能覆盖的最多公共场所的数量。
输入输出样例
输入样例#1:
1
2
4 4 10
6 6 20
输出样例#1:
1 30
说明
对于100%的数据,1≤d≤20,1≤n≤20, 0≤x≤128,0≤y≤128,0<k≤1,000,000。
思路
对于每一个(x,y,k),在(x-d~x+d , y-d~y+d)的坐标中的ans都加上k;
表示在(x-d~x+d , y-d~y+d)的范围内放置路由器,都能覆盖到(x,y),
将他的值加上(x,y)处的公共场所数
最后循环找最大值。
代码
#include<bits/stdc++.h>
using namespace std;
int d,a[129][129];
void fd(int x,int y,int z) {
for (int i=-d; i<=d; i++)
for (int j=-d; j<=d; j++)
if (i+x>=0&&j+y>=0&&i+x<129&&j+y<129)
a[x+i][y+j]+=z;
return;
}
int main()
{
memset(a,0,sizeof(a));
int x,y,n,z,ans=0,sum=0;
scanf("%d%d",&d,&n);
for (int i=1; i<=n; i++) {
scanf("%d%d%d",&x,&y,&z);
fd(x,y,z);
}
for (int i=0; i<=128; i++)
for (int j=0; j<=128; j++) {
if (a[i][j]==ans)
++sum;
if (a[i][j]>ans) {
ans=a[i][j];
sum=1;
}
}
printf("%d %d",sum,ans);
return 0;
}
联合权值
题目描述
无向连通图G 有n 个点,n - 1 条边。点从1 到n 依次编号,编号为 i 的点的权值为W i ,每条边的长度均为1 。图上两点( u , v ) 的距离定义为u 点到v 点的最短距离。对于图G 上的点对( u, v) ,若它们的距离为2 ,则它们之间会产生Wu×Wv 的联合权值。
请问图G 上所有可产生联合权值的有序点对中,联合权值最大的是多少?所有联合权值之和是多少?
输入输出格式
输入格式:
输入文件名为link .in。
第一行包含1 个整数n 。
接下来n - 1 行,每行包含 2 个用空格隔开的正整数u 、v ,表示编号为 u 和编号为v 的点之间有边相连。
最后1 行,包含 n 个正整数,每两个正整数之间用一个空格隔开,其中第 i 个整数表示图G 上编号为i 的点的权值为W i 。
输出格式:
输出文件名为**link .out **。
输出共1 行,包含2 个整数,之间用一个空格隔开,依次为图G 上联合权值的最大值和所有联合权值之和。由于所有联合权值之和可能很大,输出它时要对10007 取余。
输入输出样例
输入样例#1:
5
1 2
2 3
3 4
4 5
1 5 2 3 10
输出样例#1:
20 74
说明
本例输入的图如上所示,距离为2 的有序点对有(1,3) 、( 2,4) 、( 3,1) 、( 3,5) 、( 4,2) 、( 5,3) 。
其联合权值分别为2 、15、2 、20、15、20。其中最大的是20,总和为74。
【数据说明】
对于30% 的数据,1 < n≤ 100 ;
对于60% 的数据,1 < n≤ 2000;
对于100%的数据,1 < n≤ 200 , 000 ,0 < wi≤ 10, 000 。
思路
枚举每一个点;
然后枚举可以连到他的点;
然后对着些点直接统计答案就好
代码
#include<cstdio>
#include<iostream>
using namespace std;
const int N=2e5+5,mo=10007;
struct cs{int to,nxt;}a[N*2];
int head[N],ll,v[N];
int n,ans,x,y,maxans;
void init(int x,int y){
a[++ll].to=y;
a[ll].nxt=head[x];
head[x]=ll;
}
void work(int x){
int sum=0,ma=0,m=0;
for(int k=head[x];k;k=a[k].nxt){
if(v[a[k].to]>ma){
m=ma;
ma=v[a[k].to];
}else
if(v[a[k].to]>m)m=v[a[k].to];
ans=(ans+sum*v[a[k].to])%mo;
sum=(sum+v[a[k].to])%mo;
}
maxans=max(maxans,ma*m);
}
int main(){
scanf("%d",&n);
for(int i=1;i<n;i++){
scanf("%d%d",&x,&y);
init(x,y); init(y,x);
}
for(int i=1;i<=n;i++)scanf("%d",&v[i]);
for(int i=1;i<=n;i++)work(i);
printf("%d %d",maxans,(ans*2)%mo);
}
寻找道路
题目描述
在有向图G 中,每条边的长度均为1 ,现给定起点和终点,请你在图中找一条从起点到终点的路径,该路径满足以下条件:
1 .路径上的所有点的出边所指向的点都直接或间接与终点连通。
2 .在满足条件1 的情况下使路径最短。
注意:图G 中可能存在重边和自环,题目保证终点没有出边。
请你输出符合条件的路径的长度。
输入输出格式
输入格式:
输入文件名为road .in。
第一行有两个用一个空格隔开的整数n 和m ,表示图有n 个点和m 条边。
接下来的m 行每行2 个整数x 、y ,之间用一个空格隔开,表示有一条边从点x 指向点y 。
最后一行有两个用一个空格隔开的整数s 、t ,表示起点为s ,终点为t 。
输出格式:
输出文件名为**road .out **。
输出只有一行,包含一个整数,表示满足题目᧿述的最短路径的长度。如果这样的路径不存在,输出- 1 。
输入输出样例
输入样例#1:
3 2
1 2
2 1
1 3
输出样例#1:
-1
输入样例#2:
6 6
1 2
1 3
2 6
2 5
4 5
3 4
1 5
输出样例#2:
3
说明
解释1:
如上图所示,箭头表示有向道路,圆点表示城市。起点1 与终点3 不连通,所以满足题
目描述的路径不存在,故输出- 1 。
解释2:
如上图所示,满足条件的路径为1 - >3- >4- >5。注意点2 不能在答案路径中,因为点2连了一条边到点6 ,而点6 不与终点5 连通。
数据范围
对于30%的数据,0<n≤10,0<m≤20;
对于60%的数据,0<n≤100,0<m≤2000;
对于100%的数据,0<n≤10,000,0<m≤200,000,0<x,y,s,t≤n,x≠t。
思路
- 只需要在满足条件上的点进行最短路即可
- 那么这么找满足条件的点呢,
- 先在循环中就标记每个点的出度,
- 我们现在在终点进行一次bfs,经过一个点那么它的num数组++,也就是标记一下它的入度,
- 那么spfa时满足条件的点就是出度等于入度的点
很简单
代码
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <string>
#include <iostream>
#include <queue>
using namespace std;
const int INF=100000111;
int n,m,s,t,tail,vis[350001],head1[350001],head2[350001],sign[350001],inqueue[350001],chu[350001],num[350001];
struct node {
int u,v,next;
};
node r1[350001],r2[350001];
queue<int>q;
void add(int x,int y) {
r1[++tail].u=x;
r1[tail].v=y;
r1[tail].next=head1[x];
head1[x]=tail;
r2[tail].u=y;
r2[tail].v=x;
r2[tail].next=head2[y];
head2[y]=tail;
}
void bfs(int sx) {
q.push(sx);
sign[sx]=1;
while (!q.empty()) {
int sx=q.front();
q.pop();
for (int i=head2[sx];i;i=r2[i].next) {
int nex=r2[i].v;
num[nex]++;
if (!sign[nex]) {
sign[nex]=1;
q.push(nex);
}
}
}
}
void spfa(int sx,int sy) {
for (int i=1;i<=n;i++)
vis[i]=INF;
q.push(sx);
inqueue[sx]=1;
vis[sx]=0;
while (!q.empty()) {
int sx=q.front();
q.pop();
for (int i=head1[sx];i;i=r1[i].next) {
int nex=r1[i].v;
if (vis[sx]+1 < vis[nex] && num[nex]==chu[nex]) {
vis[nex]=vis[sx]+1;
if (!inqueue[nex]) {
inqueue[nex]=1;
q.push(nex);
}
}
}
}
if (vis[sy] == INF) printf("-1");
else printf("%d",vis[sy]);
}
int main()
{
scanf("%d%d",&n,&m);
for (int i=1;i<=m;i++) {
int x,y;
scanf("%d%d",&x,&y);
add(x,y);
chu[x]++;
}
scanf("%d%d",&s,&t);
bfs(t);
spfa(s,t);
return 0;
}
飞扬的小鸟
原题
Flappy Bird 是一款风靡一时的休闲手机游戏。玩家需要不断控制点击手机屏幕的频率来调节小鸟的飞行高度,让小鸟顺利通过画面右方的管道缝隙。如果小鸟一不小心撞到了水管或者掉在地上的话,便宣告失败。
- 为了简化问题,我们对游戏规则进行了简化和改编:
游戏界面是一个长为 n,高为 m 的二维平面,其中有 k 个管道(忽略管道的宽度)。
小鸟始终在游戏界面内移动。小鸟从游戏界面最左边任意整数高度位置出发,到达游戏界面最右边时,游戏完成。
小鸟每个单位时间沿横坐标方向右移的距离为 1,竖直移动的距离由玩家控制。如果点击屏幕,小鸟就会上升一定高度 X,每个单位时间可以点击多次,效果叠加;如果不点击屏幕,小鸟就会下降一定高度 Y。小鸟位于横坐标方向不同位置时,上升的高度 X 和下降的高度 Y 可能互不相同。
小鸟高度等于 0 或者小鸟碰到管道时,游戏失败。小鸟高度为 m 时,无法再上升。
现在,请你判断是否可以完成游戏。如果可以,输出最少点击屏幕数;否则,输出小鸟最多可以通过多少个管道缝隙。
输入输出
输入格式
第 1 行有 3个整数 n,m,,分别表示游戏界面的长度,高度和水管的数量,每两个整数之间用一个空格隔开;
接下来的 nn 行,每行 2 个用一个空格隔开的整数 X 和 Y,依次表示在横坐标位置 0∼n−10∼n−1 上玩家点击屏幕后,小鸟在下一位置上升的高度 X,以及在这个位置上玩家不点击屏幕时,小鸟在下一位置下降的高度 Y。
接下来 kk 行,每行 33 个整数 P,L,HP,L,H,每两个整数之间用一个空格隔开。每行表示一个管道,其中 PP 表示管道的横坐标,LL 表示此管道缝隙的下边沿高度,HH 表示管道缝隙上边沿的高度(输入数据保证 PP 各不相同,但不保证按照大小顺序给出)。
输出格式
共两行。
第一行,包含一个整数,如果可以成功完成游戏,则输出 11,否则输出 00。
第二行,包含一个整数,如果第一行为 11,则输出成功完成游戏需要最少点击屏幕数,否则,输出小鸟最多可以通过多少个管道缝隙。
样例一
input
10 10 6
3 9
9 9
1 2
1 3
1 2
1 1
2 1
2 1
1 6
2 2
1 2 7
5 1 5
6 3 5
7 5 8
8 7 9
9 1 3
output
1
6
样例二
input
10 10 4
1 2
3 1
2 2
1 8
1 8
3 2
2 1
2 1
2 2
1 2
1 0 2
6 7 9
9 1 4
3 8 10
output
0
3
限制与约定
对于 30%的数据:5≤n≤10,5≤m≤10,k=05≤n≤10,5≤m≤10,k=0,保证存在一组> 最优解使得同一单位时间最多点击屏幕 33 次;
对于 50%的数据:5≤n≤20,5≤m≤105≤n≤20,5≤m≤10,保证存在一组最优解使得同一单位时间最多点击屏幕 33 次;
对于 70%的数据:5≤n≤1000,5≤m≤1005≤n≤1000,5≤m≤100;
对于 100%的数据:5≤n≤10000,5≤m≤1000,0≤k<n,0<X<m,0<Y<m,0<P<n,0≤L<H≤m,L+1<H5≤n≤10000,5≤m≤1000,0≤k<n,0<X<m,0<Y<m,0<P<n,0≤L<H≤m,L+1<H。
时间限制:1s1s
空间限制:128MB
说明
【输入输出样例说明】
如下图所示,蓝色直线表示小鸟的飞行轨迹,红色直线表示管道。
【数据范围】
对于30% 的数据:5 ≤ n ≤ 10,5 ≤ m ≤ 10,k = 0 ,保证存在一组最优解使得同一单位时间最多点击屏幕3 次;
对于50% 的数据:5 ≤ n ≤ 2 0 ,5 ≤ m ≤ 10,保证存在一组最优解使得同一单位时间最多点击屏幕3 次;
对于70% 的数据:5 ≤ n ≤ 1000,5 ≤ m ≤ 1 0 0 ;
对于100%的数据:5 ≤ n ≤ 100 0 0 ,5 ≤ m ≤ 1 0 00,0 ≤ k < n ,0<X < m ,0<Y <m,0<P <n,0 ≤ L < H ≤ m ,L +1< H 。
思路
首先想到设f[i][j]表示到第i行第j列所需要的最少点击屏幕次数。转移方程为
f[ i ][ j ]=min{f[ i-1 ][ j - k*x[i-1] ] + k} (1<= k <= j/x) 上升——①
f[ i ][ j ]=min{f[ i-1 ][ j + y[i-1] } ( j + y[i-1] <= m) 下降
显然,下降可以O(1)转移,主要问题在上升的转移。
我们将上升的方程变一下:
f[ i ][ j - x[i-1] ]=min{f[ i-1 ][ (j - x[i-1]) - (k-1)*x[i-1] ] + k -1} ——②
这是 f[ i ][ j - x[i-1] ] 的转移。
由 ② 化简可得:
f[ i ][ j - x[i-1] ]=min{f[ i-1 ][ j - kx[ i-1] ] + k -1}——③
由①③消去f[ i-1 ][ j - kx[ i-1] ]+k可得
f[ i ][ j ]= f[ i ][ j - x[ i-1 ] ]+1
于是就可以O(n*m)的时间内出解
代码
#include <map>
#include <set>
#include <cmath>
#include <ctime>
#include <queue>
#include <stack>
#include <cstdio>
#include <string>
#include <vector>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define rg register
using namespace std;
#define ll long long
inline int gi()
{
rg bool b=0;
rg int r=0;
char c=getchar();
while(c<'0' || c>'9')
{
if(c=='-') b=!b;
c=getchar();
}
while(c>='0' && c<='9')
{
r=r*10+c-'0';
c=getchar();
}
if(b) return -r;
return r;
}
const int inf = 2100000000, N = 10005, M = 1005;
int n,m,q,x[N],y[N],f[N][M];
bool b[N];
struct data
{
int up,down;
} da[N];
int main()
{
freopen ("birda.in","r",stdin);
freopen ("birda.out","w",stdout);
int i,p,j,k,cnt,ans;
n=gi(), m=gi(), q=gi();
for (i=0; i<n; i++) x[i]=gi(), y[i]=gi();
for (i=1; i<=n; i++) da[i].down=0, da[i].up=m+1;
for (i=0; i<q; i++) p=gi(), da[p].down=gi(), da[p].up=gi(); //一定要加,不然会影响到第65行的循环枚举
for (i=1; i<=n; i++) for (j=0; j<=m; j++) f[i][j]=inf; //初始化。0位置除地面外都为0
f[0][0]=inf;
for (i=1; i<=n; i++)
{
for (j=x[i-1]; j<=m; j++)
{
f[i][j]=min(f[i][j],f[i-1][j-x[i-1]]+1), f[i][j]=min(f[i][j],f[i][j-x[i-1]]+1); //更新解,先不考虑水管
if (j == m) //特殊判断 j==m 的情况,因为不能超过 m ,所以有多种转移
for (k=m-x[i-1]; k<=m; k++)
f[i][j]=min(f[i][j],f[i-1][k]+1), f[i][j]=min(f[i][j],f[i][k]+1);
}
for (j=da[i].down+1; j<da[i].up; j++) //处理下落,必须是合法的
if (j+y[i-1] <= m)
f[i][j]=min(f[i][j],f[i-1][j+y[i-1]]);
for (j=1; j<=da[i].down; j++) f[i][j]=inf; //考虑水管,去掉不合法的解
for (j=m; j>=da[i].up; j--) f[i][j]=inf;
}
cnt=q,ans=inf;
for (i=n; i>=1; i--)
{
for (j=1; j<=m; j++) ans=min(ans,f[i][j]); //若 ans 有值则代表能到达。
if (ans < inf) break;
if (da[i].up <= m) cnt--; // da[i].up <= m 才是真水管
}
if (cnt == q) printf("1\n%d\n",ans);
else printf("0\n%d\n",cnt);
return 0;
}
解方程
题目描述
已知多项式方程:
a0+a1x+a2x^2 +...+anx^n=00
求这个方程在[1, m ] 内的整数解(n 和m 均为正整数)
输入输出格式
输入格式:
输入文件名为equation .in
。
输入共n + 2 行。
第一行包含2 个整数n 、m ,每两个整数之间用一个空格隔开。
接下来的n+1 行每行包含一个整数,依次为a0,a1,a2..an
输出格式:
输出文件名为equation .out
。
第一行输出方程在[1, m ] 内的整数解的个数。
接下来每行一个整数,按照从小到大的顺序依次输出方程在[1, m ] 内的一个整数解。
输入输出样例
输入样例#1:
2 10
1
-2
1
输出样例#1:
1
1
输入样例#2:
2 10
2
-3
1
输出样例#2:
2
1
2
说明
对于30%的数据:0<n<=2,|ai|<=100,an!=0,m<100
对于50%的数据:0<n<=100,|ai|<=10^100,an!=0,m<100
对于70%的数据:0<n<=100,|ai|<=10^10000,an!=0,m<10000
对于100%的数据:0<n<=100,|ai|<=10^10000,an!=0,m<1000000
思路
秦九韶算法
其实我们可以把左边的式子当成一个算式来计算,从1到m枚举,只要结果是0,那么当前枚举到的值就是这个等式的解了。可以通过编写一个bool函数来判断算式的值是不是0~
代码
#include<algorithm>
#include<iostream>
#include<iomanip>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
typedef long long ll;
const int p=1000000007;//取模比较方便qwq为了出现奇怪的错误建议多模几个质数
bool t=true;//用来判断是否有解
int n,m,ans,cnt,sum=0;//cnt记录解的个数;sum用来计算多项式的结果
int A[103],key[1000003];
//A[]记录式中的a0,a1,a2(注意是以0为起点)
//key记录每个解的值
ll read()//读入优化(似乎不加会T两个点w)
{
ll sum=0,fg=1;
char c=getchar();
while(c < '0' || c > '9')
{
if(c=='-') fg=-1;//如果读到负号则记录
c=getchar();
}
while(c >='0' && c <='9')
{
sum=((sum*10)+c-'0')%p;
//注意因为A[]可能很大,所以读入时就要进行取模操作
c=getchar();
}
return sum*fg;
//如果是负数(fg==-1,即读到了负号)那么返回的值为负数
}
void print(int x)//输出优化(这个可以不加qwq)
{
if(x<0)
{
putchar('-');
x=-x;
}
if(x>9)
{
print(x/10);
}
putchar(x%10+'0');
}
bool calc(ll x)
{
sum=0;//一定要清零!!!(不然只有10分呜呜呜)
for(ll i=n;i>=0;i--)
{
sum=((A[i]+sum)*x)%p;
//这里套用秦九韶算法求多项式的值
}
return !sum;//如果答案是0说明x值为该多项式的解,返回1(true)
}
int main()
{
n=read();
m=read();
for(ll i=0;i<=n;i++)
{
A[i]=read();
}
for(ll i=1;i<=m;i++)
{
if(calc(i))//如果返回的是1(true)则说明有解
{
t=false;
ans++;//记录答案个数
key[++cnt]=i;//记录每个解的值
}
}
if(t)
{
cout<<ans<<endl;//如果t未改变则说明解的个数为0
return 0;
}
print(ans);
printf("\n");
for(ll i=1;i<=cnt;i++)
{
print(key[i]);
printf("\n");
}
return 0;
}