题解
pdf格式题解:这里
事先吐槽出题人!!题目难度根本不是递增的!$A$题最难不接受反驳
A无序组数
如果不算无序的话,很好做。
线性筛一发之后枚举每个数的因数有多少,
之后两边乘起来就是答案。
现在我们考虑无序。
当且仅当两个数同时是$m,n$的约数是会有影响,
所以在统计一下这两个数同时有的约数就好了$……$
考后$ac$代码
#include<bits/stdc++.h> using namespace std; int d[100010]; int T; int main(){ for(int i=1;i<100010;i++) for(int j=i;j<100010;j+=i) d[j]++; scanf("%d",&T); for(;T--;){ int a,b; scanf("%d%d",&a,&b); printf("%d\n",d[a]*d[b]-d[__gcd(a,b)]*(d[__gcd(a,b)]-1)/2); } return 0; }
复杂度$O(n+t)$
B路径数量
裸的$Folyed$传递闭包,
矩阵快速幂一下就好。
其实直接矩阵乘就能过
复杂度$O(n^3k)$或者$O(n^3logk)$
不知道的可以自行出门左转上度娘
//#include"suqingnian.h" #include<iostream> #include<cstdio> #include<algorithm> #include<ctime> #include<cstring> #define int long long using namespace std; int n,k; struct _Martix{ int num[210][210]; _Martix(){memset(num,0,sizeof(num));} friend _Martix operator* ( const _Martix &__a,const _Martix &__b) { _Martix __c; int _n=n; for( int _k = 1 ; _k <= _n ; _k ++ ) for( int _i = 1 ; _i <= _n ; _i ++ ) for( int _j = 1; _j <= _n ; _j ++ ) __c.num[_i][_j] += __a.num[_i][_k] * __b.num[_k][_j] ; return __c; } }q; _Martix pow2(_Martix a,long long b) { _Martix c; for(int i=1;i<=n;i++) c.num[i][i]=1; for(;b;b>>=1,a=a*a) if(b&1) c=c*a; return c; } signed main() { scanf("%lld%lld",&n,&k); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) scanf("%lld",&q.num[i][j]); q=pow2(q,k); printf("%lld",q.num[1][n]); return 0; }
C数列下标
看看这数据范围
$n^2$暴力可过
模拟一下就好
贴代码:
#pragma gcc optimize(2) #include<bits/stdc++.h> using namespace std; int a[100010],n; int main(){ scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&a[i]); for(int i=1;i<=n;i++){ int ans=0; for(int j=i+1;j<=n;j++) if(a[j]>a[i]){ ans=j; break; } printf("%d ",ans); } return 0; }
D星光晚餐
原题大作战$*1$,出门左拐洛谷开灯。
结论是,直接开根号下取整输出就好。
$O(1)$
#include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #include<cstring> using namespace std; long long n; int main() { scanf("%lld",&n); long long ans=sqrt(n); printf("%lld",ans); return 0; }
E括号序列
原题大作战$*2$,出门直走百度题面(但是窝忘了哪那道题了)
我们贪心的想每个右括号要不要换,尽量把左括号放到左边,右括号放到右边
直接说解法。用一个栈维护序列,如果是右括号,直接压栈
之后统计一发答案就行了
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<stack> using namespace std; char a[5000050]; stack<char> st; int n;int cnt; int main() { scanf("%d",&n); cin>>a; for(int i=0;i<n;i++) if(a[i]=='(') st.push('('); else{ if(st.empty()||st.top()==')') st.push(')'); else st.pop(),cnt++; } printf("%d",(n/2-cnt+1)/2); return 0; }
复杂度$O(n)$
打表好题
先说一下第$i$组数据的输入就是$i$个$7$
普通的$java$,高精打表就不说了
这里讲个比较块的方法
首先我们想暴力
枚举$n \in [1,+\infty)$之后判断与$x^x$大小
然后,发现太大,所以日常套路一下。
两边取自然对数。
左边就变成
$\sum_{i=1}^{n} ln(i)$
右边变成
$xln(x)$
这样开$long\ double$就可以不用考虑精度问题了,复杂度$O$答案
然后常识告诉我们,第$i$组的答案的位数是$i$
然后就打一发表就行,然后最后一个点窝打了$5min$前面是秒出$……$
#include<iostream> #include<cstdio> #include<algorithm> #include<ctime> #include<cmath> #include<cstring> using namespace std; long long n; int main() { scanf("%lld",&n); if(n==7ll) puts("10"); if(n==77ll) puts("94"); if(n==777ll) puts("892"); if(n==7777ll) puts("8640"); if(n==77777ll) puts("84657"); if(n==777777ll) puts("834966"); if(n==7777777ll) puts("8267019"); if(n==77777777ll) puts("82052137"); if(n==777777777ll) puts("815725636"); if(n==7777777777ll) puts("8118965902"); return 0; }
这份题解会等出成绩之后做相应调整$……$
并且会贴上代码
如果窝爆零了就会删除
以上是窝考场上想出来的
ABC都有锅