1. 开a,b变量+输入
*特殊情况:如果a等于1直接输出1
2. 开变量n,每次循环里会增加一次a
3. for循环0~b-1次循环求幂
n求幂,每次乘a
判断最新的数字是否大于10^9
是:输出-1,结束运行
否:继续for循环
4. 输出最终答案n
1. 两个变量记得开ll或者ull 都行 反正int过不了
2. 场上freopen的文件名别写错
3. 想我这种手敲了10^9的数清楚几个0
4. n变量初始值为1
- #include
- using namespace std;
- int main(){
- long long a,b,n=1;
- cin>>a>>b;
- if(a==1){
- cout<<"1";
- return 0;
- }
- else{
- for(long long i=0;i
- n*=a;
- if(n>1000000000){
- cout<<"-1";
- return 0;
- }
- }
- }
- cout<
- return 0;
- }
第二题 解密
【题目描述】
给定一个正整数
k,有
k 次询问,每次给定三个正整数
n
i
, e
i
, d
i,求两个正整数
p
i
, q
i,
使
n
i =
p
i
×
q
i
, e
i
×
d
i = (
p
i
− 1)(
q
i
− 1) + 1。
【输入格式】
从文件
decode.in 中读入数据。
第一行一个正整数
k,表示有
k 次询问。
接下来
k 行,第
i 行三个正整数
n
i
, d
i
, e
i。
【输出格式】
输出到文件
decode.out 中。
输出
k 行,每行两个正整数
p
i
, q
i 表示答案。
为使输出统一,你应当保证
p
i
≤
q
i。
如果无解,请输出 NO。
【样例 1 输入】
10
770 77 5
633 1 211
545 1 499
683 3 227
858 3 257
723 37 13
572 26 11
867 17 17
829 3 263
528 4 109
【样例 1 输出】
2 385
NO
NO
NO
11 78
3 241
2 286
NO
NO
6 88
解题思路
简单来说,就是求一元二次方程然后带进代码里求值就可以了(排除特殊NO情况)!!!!!看到k , n , e , d 的范围就知道要推公式,数据范围提示很明显的了。所以m是怎么来的呢? 很简单 如果距离事1,就输出NO,同样如果x小于0也会输出NO。接下来用一般的方法就行了
解题流程
1. 分两个函数(方便看)先分read和主函数
2. 带入read函数,判断数字和符号
3. 把NO的情况单独分出来(m如果距离是1,x<0)
4. 带入一元二次公式 求p,q
5. 输出
代码
- #include
- #define ll long long
- using namespace std;
- const int mod=1e9+7;
- const int INF=0x3f3f3f3f;
-
- inline ll read()
- {
- ll x=0,f=1;char c=getchar();
- while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
- while(c>='0'&&c<='9'){x=x*10+c-'0',c=getchar();}
- return x*f;
- }
-
- int main(){
- int k=read();
- while(k--)
- {
- ll n=read(),d=read(),e=read();
- ll x=e*d-n-2;
- x=-x;
- double s=sqrt(x*x-4*n);
- if(x<0||x*x-4*n<0||s!=int(s))
- {
- printf("NO\n");
- continue;
- }
- int ss=s;
- if((-x-ss)&1||(-x+ss)&1)
- {
- printf("NO\n");
- return 0;
- }
- int yy=(-x-ss)/(-2),xx=(-x+ss)/(-2);
- if(xx<=0||yy<=0)
- {
- printf("NO\n");
- return 0;
- }
- printf("%d %d\n",xx,yy);
- }
- return 0;
- }
第三题 逻辑表达式
【题目描述】
逻辑表达式是计算机科学中的重要概念和工具,包含逻辑值、逻辑运算、逻辑运算
优先级等内容。
在一个逻辑表达式中,元素的值只有两种可能:
0
(表示假)和
1
(表示真)。元素
之间有多种可能的逻辑运算,本题中只需考虑如下两种:“与”(符号为
&
)和“或”(符
号为
|
)。其运算规则如下:
0
&
0 = 0
&
1 = 1
&
0 = 0
,
1
&
1 = 1
;
0
|
0 = 0
,
0
|
1 = 1
|
0 = 1
|
1 = 1
。
在一个逻辑表达式中还可能有括号。规定在运算时,括号内的部分先运算;两种运
算并列时,
&
运算优先于
|
运算;同种运算并列时,从左向右运算。
比如,表达式
0|1&0
的运算顺序等同于
0|(1&0)
;表达式
0&1&0|1
的运算顺序等
同于
((0&1)&0)|1
。
此外,在
C++
等语言的有些编译器中,对逻辑表达式的计算会采用一种“短路”
的策略。:在形如
a&b
的逻辑表达式中,会先计算
a
部分的值,如果
a
= 0
,那么整个
逻辑表达式的值就一定为
0
,故无需再计算
b
部分的值;同理,在形如
a|b
的逻辑表达
式中,会先计算
a
部分的值,如果
a
= 1
,那么整个逻辑表达式的值就一定为
1
,无需
再计算
b
部分的值。
现在给你一个逻辑表达式,你需要计算出它的值,并且统计出在计算过程中,两种
类型的“短路”各出现了多少次。需要注意的是,如果某处“短路”包含在更外层被“短
路”的部分内则不被统计,如表达式
1|(0&1)
中,尽管
0&1
是一处“短路”,但由于外
层的
1|(0&1)
本身就是一处“短路”,无需再计算
0&1
部分的值,因此不应当把这里的
0&1
计入一处“短路”。
【输入格式】
从文件
expr.in
中读入数据。
输入共一行,一个非空字符串
s
表示待计算的逻辑表达式。
【输出格式】
输出到文件
expr.out
中。
输出共两行,第一行输出一个字符
0
或
1
,表示这个逻辑表达式的值;第二行输
出两个非负整数,分别表示计算上述逻辑表达式的过程中,形如
a&b
和
a|b
的“短路”
各出现了多少次。
解题思路
直接开数组,分calc和build函数分别为运算,和判断符号的函数。用布尔类的函数dfs返回每个值,分别是 ( 和 | 和 &。到时候带入build和calc所以调用dfs函数的数里面就是build。dfs(build())
解题流程
1. 分4个函数 calc做运算 build判断01和符号 dfs(布尔)做符号判断的根本 和主函数
2. 输入字符串
3. 拆分成op和num 逐个运算
4. 计算“短路”情况“
5. 两个结果输出
代码
- #include
- using namespace std;
-
- int n,ch[1000010][2],root,num[1000010],op[1000010],pri[1<<10],topn,topo;
- char s[1000010];
- void calc(){
- int u=op[topo];
- ch[u][0]=num[topn-1],ch[u][1]=num[topn];
- topo--,topn-=2,num[++topn]=u;
- }
- int build(){
- topn=0,topo=0;
- s[0]='(',s[n+1]=')';
- for(int i=0;i<=n+1;i++){
- if(s[i]=='0'||s[i]=='1') num[++topn]=i;
- else if(s[i]=='(') op[++topo]=i;
- else if(s[i]=='&'||s[i]=='|'){
- while(topo&&pri[s[op[topo]]]
calc(); - op[++topo]=i;
- }else if(s[i]==')'){
- while(topo&&pri[s[op[topo]]]
calc(); -
- topo--;
- }
- }
-
- return num[topn];
- }
- int cnt1,cnt0;
- bool dfs(int u){
- if(s[u]=='0') return 0;
- if(s[u]=='1') return 1;
- if(s[u]=='&'){
- if(!dfs(ch[u][1])) return cnt0++,0;
- return dfs(ch[u][0]);
- }
- if(s[u]=='|'){
- if(dfs(ch[u][1])) return cnt1++,1;
- return dfs(ch[u][0]);
- }
- return -1;
- }
- int main(){
- scanf("%s",s+1),n=strlen(s+1);
- pri['(']=1e9,pri['|']=1,pri['&']=0,pri[')']=1e9-1;
- reverse(s+1,s+n+1);
- for(int i=1;i<=n;i++){
- if(s[i]=='(') s[i]=')';
- else if(s[i]==')') s[i]='(';
- }
- printf("%d\n",dfs(build()));
- printf("%d %d\n",cnt0,cnt1);
- return 0;
- }
第四题 上升点列
【题目描述】
在一个二维平面内,给定
n
个整数点
(
x
i
, y
i
)
,此外你还可以自由添加
k
个整数点。
你在自由添加
k
个点后,还需要从
n
+
k
个点中选出若干个整数点并组成一个序列,使
得序列中任意相邻两点间的欧几里得距离恰好为
1
而且横坐标、纵坐标值均单调不减,
即
x
i
+1
−
x
i
= 1
, y
i
+1
=
y
i
或
y
i
+1
−
y
i
= 1
, x
i
+1
=
x
i
。请给出满足条件的序列的最大长
度。
【输入格式】
从文件
point.in
中读入数据。
第一行两个正整数
n, k
分别表示给定的整点个数、可自由添加的整点个数。
接下来
n
行,第
i
行两个正整数
x
i
, y
i
表示给定的第
i
个点的横纵坐标。
【输出格式】
输出到文件
point.out
中。
输出一个整数表示满足要求的序列的最大长度。
【样例
1
输入】
8 2
3 1
3 2
3 3
3 6
1 2
2 2
5 5
5 3
【样例
1
输出】
8
解题思路
状态dp题,但是要分别xy点转移方程。先看n , k 的范围,显然可在O ( n 2 k ) 复杂度解决。状态怎么找呢?看答案的转移需要哪些条件,其转移与序列最后一个点的坐标和添加点的个数有关。
解题流程
1. 分布尔函数cmp 和猪函数main。cmp创建数轴上的点Node,主函数运行
2. 输入nk和所有点
3. 判断绝对值,输出ans+k的值
代码
- #include
- using namespace std ;
- const int Max = 5e2 + 10 , TIL = ( 1 << 28 ) ;
- struct Node { int X , Y ; } T[Max] ;
- int F[Max][Max] , Con[Max][Max] ;
- int N , K ;
- bool CMP( Node A , Node B ) {
- if( A.X == B.X ) return A.Y < B.Y ;
- else return A.X < B.X ;
- }
- int Ans ;
- int main( ) {
- scanf("%d%d" , &N , &K ) ;
- for(int i = 1 ; i <= N ; i ++ ) scanf("%d%d" , &T[i].X , &T[i].Y ) , Con[i][0] = 0 ;
- sort( T + 1 , T + N + 1 , CMP ) ;
- for(int i = 1 ; i <= N ; i ++ ) for(int l = 1 ; l <= N ; l ++ )
- Con[i][l] = abs( T[i].X - T[l].X ) + abs( T[i].Y - T[l].Y ) - 1 ;
- for(int i = 1 ; i <= N ; i ++ ) F[i][0] = 1 ;
- for(int P = false ; P <= K ; P ++ ) for(int i = 2 ; i <= N ; i ++ ) for(int l = 0 ; l <= i - 1 ; l ++ )
- if( Con[i][l] <= P && T[l].X <= T[i].X && T[l].Y <= T[i].Y ) F[i][P] = max( F[i][P] , F[l][P - Con[i][l]] + 1 ) ;
- for(int i = 1 ; i <= N ; i ++ ) for(int P = false ; P <= K ; P ++ ) Ans = max( Ans , F[i][P] ) ;
- printf("%d\n" , Ans + K ) ;
- return false ;
- }