T1
#include<bits/stdc++.h> //Ithea Myse Valgulious
using namespace std;
int gcd(int a,int b){
return b?gcd(b,a%b):a;
}
int main(){
int i,j,n,k,x,cnt=0;
scanf("%d%d",&n,&k);
for (i=1;i<=n;++i) {
cin>>x;
if (x>k) cnt+=gcd(x,k);
}
cout<<cnt<<endl;
}
输入:
7 2
1 5 2 3 4 6 8
T2
#include<bits/stdc++.h> //Ithea Myse Valgulious
using namespace std;
int main(){
int i,j,k;
string s; cin>>s;
int ans=0;
for (i=0;i<s.size();++i)
for (j=i+1;j<s.size();++j)
for (k=j+1;k<s.size();++k)
if (s[i]=='Q'&&s[j]=='A'&&s[k]=='Q')
ans++;
cout<<ans<<endl;
}
输入1:
QQQAAAQQQ
输入2:
QAQAQAQAQ
T3
#include<bits/stdc++.h> //Ithea Myse Valgulious
using namespace std;
int dp[10505];
int main(){
int i,j,n,a[105];
scanf("%d",&n);
for (i=1;i<=n;i++)
scanf("%d",&a[i]),dp[a[i]]++;
sort(a+1,a+n+1);
for (i=1;i<=n;i++)
for (j=1;j<=n;j++)
dp[i]+=dp[a[j]];
for (i=1;i<=n;++i)
cout<<dp[i]<<" ";
}
输入:
5
5 1 4 3 2
T4
#include<bits/stdc++.h> //Ithea Myse Valgulious
using namespace std;
const int mulu=2e7;
typedef int fuko[mulu|10];
fuko p,pr;
void gpr(int n){
int i,j;
for (i=2;i<=n;++i) {
if (!p[i]) p[i]=pr[++*pr]=i;
for (j=1;j<=*pr;j++) {
if (pr[j]*i>n) break;
p[pr[j]*i]=pr[j];
if (i%pr[j]==0) break;
}
}
}
int main(){
gpr(mulu);
int i,n;
scanf("%d",&n);
printf("%d=",n);
for (;n>1;n/=p[n]) {
printf("%d",p[n]);
if (n^p[n]) printf("*");
}
}
输入1:
18
输入2:
1001
输入3:
30031
输入4:
19260817
T5
#include<bits/stdc++.h> //Ithea Myse Valgulious
using namespace std;
typedef long long ll;
const int yuzu=1e5,mod=1e9+7;
typedef ll fuko[yuzu|10];
fuko jic,inv;
ll kasumi(ll a,ll b=mod-2){
ll s=1;
for (;b;b>>=1,a=a*a%mod) if (b&1) s=s*a%mod;
return s;
}
int main(){
int i,n;
scanf("%d",&n);
jic[0]=1;
for (i=1;i<=yuzu;i++) jic[i]=jic[i-1]*i%mod;
inv[yuzu]=kasumi(jic[yuzu]);
for (i=yuzu-1;~i;--i) inv[i]=inv[i+1]*(i+1)%mod;
printf("%lld\n",jic[n<<1]*inv[n]%mod*inv[n]%mod*kasumi(n+1)%mod);
}
输入1:
5
输入2:
6
T6
给出一个序列.你有两种操作:
C l r v
: 将区间
内的所有数加上
.
Q l r
. 询问
区间的和.
提示: 线段树维护区间和.如果接下来的线段树写法和你稍稍有点不同,请谅解.
#include<bits/stdc++.h> //Ithea Myse Valgulious
using namespace std;
typedef long long ll;
const int yuzu=1e5;
typedef ll karen[yuzu<<2|13];
int n,q;
struct segtree {
#define le rt<<1
#define ri le|1
#define ls le,l,mid
#define rs ri,mid+1,r
karen val,lazy;
void build(int rt=1,int l=1,int r=n){
if (l==r) {
scanf("%lld",&val[rt]);
return;
} else {
int mid=l+r>>1;
build(ls),build(rs);
val[rt]=val[le]+val[ri];
}
}
void push_down(int rt,int l,int r){
if (lazy[rt]){
int mid=l+r>>1;
lazy[le]+=lazy[rt],lazy[ri]+=lazy[rt];
______(1)_______;
val[ri]+=(r-mid)*lazy[rt];
lazy[rt]=0;
}
}
void update(int ql,int qr,int v,int rt=1,int l=1,int r=n){
if (ql>r||qr<l) return;
if (ql<=l&&qr>=r) {
val[rt]+=(r-l+1)*v;
lazy[rt]+=v;
} else {
int mid=l+r>>1;
push_down(rt,l,r);
update(ql,qr,v,ls),update(ql,qr,v,rs);
______(2)______;
}
}
ll query(int ql,int qr,int rt=1,int l=1,int r=n){
if (ql>r||qr<l) return ______(3)______;
if (ql<=l&&qr>=r) return val[rt];
int mid=l+r>>1;
______(4)_______;
return query(ql,qr,ls)+query(ql,qr,rs);
}
}my_;
int main(){
scanf("%d%d",&n,&q);
_____(5)______;
for (;q--;) {
char c=getchar();
for (;isspace(c);) c=getchar();
int l,r,v;
scanf("%d%d",&l,&r);
switch(c) {
case 'C': scanf("%d",&v),my_.update(l,r,v); break;
case 'Q': printf("%lld\n",my_.query(l,r)); break;
}
}
}
T7
给出一棵
个点的树和
组询问,每次询问
两个点的最近公共祖先.
思想:把询问离线,和询问的编号放在一起,遍历到某一个点的时候把它的询问遍历一遍,如果已经访问过,此时它在并查集中的父亲就是它们俩的最近公共祖先.
#include<bits/stdc++.h> //Ithea Myse Valgulious
using namespace std;
const int yuzu=5e5;
typedef int fuko[yuzu|10];
namespace dsu {
fuko fa;
void init(int n) { // 并查集初始化
for (int i=1; i<=n; ++i) fa[i]=i;
}
int find(int x) { //寻找父亲
return fa[x]^x?_____(1)_____:x;
}
int mg(int u,int v) { // 合并两个元素 (本题中无用)
int fu=find(u),fv=find(v);
return fu^fv?fa[fu]=fv,1:0;
}
} using dsu::find;
/*并查集,封装在namespace中.*/
typedef pair<int,int> pii; // pair 的first储存询问的对应节点,second储存询问编号.
vector<int> lj[yuzu|10]; // 这棵树的vector
vector<pii> query[yuzu|10]; // 询问的vector
fuko ans,vis; // ans数组和vis数组.
void dfs(int u,int f) {
vis[u]=1;
for (pii x:query[u])
if (vis[x.first])
______(2)______;
for (int v:lj[u]) if (v^f)
dfs(v,u),_____(3)_____;
}
int main() {
int i,n,m,rt;
scanf("%d%d%d",&n,&m,&rt);
/*rt表示这棵树的根.*/
______(4)______;
for (i=1;i<n;++i) {
int u,v;
scanf("%d%d",&u,&v);
lj[u].push_back(v);
lj[v].push_back(u);
}
for (i=1;i<=m;++i) {
int u,v;
scanf("%d%d",&u,&v);
query[u].push_back(pii(v,i));
______(5)______;
}
dfs(rt,0);
for (i=1;i<=m;++i) printf("%d\n",ans[i]);
}
T8
#include<bits/stdc++.h> //Ithea Myse Valgulious
using namespace std;
typedef long long ll;
ll dp[25][16][2][2]; int bit[25],p;
ll dfs(int now,int yu,int have,int le1,int lim) {
if (!now) return !yu&&!have;
if (!lim&&~dp[now][yu][have][le1]) return dp[now][yu][have][le1];
ll ans=0; int i,da=lim?bit[now]:9;
for (i=0; i<=da; ++i)
ans+=dfs(now-1,(yu*10+i)%13,have||le1&&i==3,i==1,lim&&i==da);
return lim?ans:dp[now][yu][have][le1]=ans;
}
ll get(ll x) {
for (p=0; x; x/=10) bit[++p]=x%10;
return dfs(p,0,0,0,1);
}
int main() {
ll l,r;
scanf("%lld%lld",&l,&r);
memset(dp,-1,sizeof dp);
printf("%lld\n",get(r)-get(l-1));
}
输入:
500 1000
T9
#include<bits/stdc++.h> //Ithea Myse Valgulious
using namespace std;
const int aoi=2038;
int a[aoi];
int main(){
int i,j,n,m;
scanf("%d",&n);
for (i=1;i<=n;++i) scanf("%d",&a[i]);
int ans=-1e9;
for (i=1;i<=n;++i) {
int tmp=0;
for (j=1;j<=n;++j) {
tmp+=a[j]*(j<=i?j:i);
}
ans=max(ans,tmp);
}
printf("%d\n",ans);
}
输入:
10
1 -2 3 -4 5 -6 7 -8 9 -10
T10
#include<bits/stdc++.h> //Ithea Myse Valgulious
using namespace std;
typedef long long ll;
const int aoi=2038;
struct node {
int a,b;
void rd(){
scanf("%d%d",&a,&b);
}
void wt(){
printf("%d %d\n",a,b);
}
bool operator <(const node &c) const {
return a*c.b^c.a*b?a*c.b<c.a*b:a<c.a;
}
} my[aoi];
int main() {
int i,j,n;
scanf("%d",&n);
for (i=1;i<=n;++i) my[i].rd();
sort(my+1,my+n+1);
for (i=1;i<=n;++i) my[i].wt();
}
输入:
16
1 1
1 2
1 3
1 4
2 1
2 2
2 3
2 4
3 1
3 2
3 3
3 4
4 1
4 2
4 3
4 4
T11
输入格式: 树节点的个数
,询问的个数
每一个节点的父亲,
个询问,你需要回答这
个询问,每个询问输出一行.
思路:预处理每一棵子树的重心,
回答询问.
为了简便,树就用vector
存储了.
#include<bits/stdc++.h> //Ithea Myse Valgulious
using namespace std;
const int yuzu=3e5;
typedef int fuko[yuzu|10];
vector<int> lj[yuzu|10];
fuko sz,ans,fa;
/*sz[u]表示以u为根的子树中的节点个数,fa[u]表示u的父亲,ans[u]表示以u为根子树的重心.*/
void dfs(int u){
____(1)____; // 给sz[u]和ans[u]赋初值
for (int v:lj[u])
dfs(v),sz[u]+=sz[v];
for (int v:lj[u])
if (_____(2)_____) ans[u]=ans[v];
for (;_____(3)_____;)
ans[u]=fa[ans[u]];
}
int main(){
int i,n,q;
scanf("%d%d",&n,&q);
for (i=2;i<=n;++i)
scanf("%d",&fa[i]),
______(4)______;
for (dfs(1);q--;)
scanf("%d",&i),
______(5)______;
}
T12
#include<bits/stdc++.h> //Ithea Myse Valgulious
using namespace std;
int main(){
int a=0;
memset(&a,0x3f,2);
printf("%08llx\n",a);
}
T13
#include<bits/stdc++.h> //Ithea Myse Valgulious
using namespace std;
int main(){
long long b=0x6f6f6f6f3f3f3f3f;
int a=b;
printf("%08llx\n",a);
}
解析
T1
没有什么目的,仅仅是一个模拟.
由于只有
个数,求出大于
的值和
的最大公约数相加即可.
T2
求字符串中含有"QAQ"子序列的数目.
第一组输入数据是一个乘法原理,
第二组输入数据暴力分类讨论一下枚举中间
的位置,用左边
的个数乘右边
的个数,
.
T3
按照输入数据模拟一下,我给的模拟复杂度不会太高只有
.
注意数组会被
一遍.
T4
观察代码.首先看gpr
这个过程,应该是一个线性筛.
然后你会发现主程序里输出了
,下面的输出里是
的类型.
因此你可以大胆猜想这个代码的目的是分解质因数.
你猜对了.
里存储的是什么呢?由于线性筛的特性,每一个数只会被筛到一次.
所以
里存储的就是
最小的质因数.
因此按照质因子从小到大的顺序输出
的质因子就可以了.
就是分解的时候算的麻烦一点.
答案就是:
18=2*3*3
1001=7*11*13
30031=59*509
19260817=19260817
输入4就不用我讲了吧.某8位质数你会不知道?
T5
数组是一个阶乘.
数组是一个阶乘逆元的线性递推.
我们要求的公式是
.
可以发现,这就求的第
项的卡特兰数.
那么游戏就结束了.
T6
意义相同的代码都算正确.
1.val[le]+=(mid-l+1)*lazy[rt]
2.val[rt]=val[le]+val[ri]
3.0
4.push_down(rt,l,r)
5.my_.build()
T7
1.fa[x]=find(fa[x])
2.ans[x.second]=find(x.first)
3.dsu::fa[v]=u // 坑点,注意本题中namespace dsu只使用了dsu::find.
4.dsu::init(n)
5.query[v].push_back(pii(u,i))
T8
很明显的一个数位dp.
那么要求
区间内满足什么条件的数呢?
来看
的五个参数.
根据ans+=dfs(now-1,(yu*10+i)%13,have||le1&&i==3,i==1,lim&&i==da);
一句可以看出:
表示当前
到了第几位,
表示当前模
的余数,
表示当前是否已经出现过
,
表示上一个数是不是
,
表示最高位有没有限制.
再根据
的判断条件,可以看出我们要求的是模
等于
,并且不含有
的数.
到
中肯定没有含有
的并且能被
整除的数.因此我们需要求的就是
到
中
的倍数,一共
个.
T9
数据范围是
,看似计算量非常大.
仔细思考,可以将该代码转化成以下的形式.
就是说,我们要求
,可以变为求原数组的后缀和的前缀和的最大值的形式,这样只要求
次,并一眼看出最大值即可.
以下代码和T9的代码是同等意义的.
#include<bits/stdc++.h> //Ithea Myse Valgulious
using namespace std;
const int aoi=2038;
int a[aoi];
int main(){
int i,j,n,m;
scanf("%d",&n);
for (i=1;i<=n;++i) scanf("%d",&a[i]);
for (i=n;i;--i) a[i]+=a[i+1];
for (i=1;i<=n;++i) a[i]+=a[i-1];
int ans=-1e9;
for (i=1;i<=n;++i) ans=max(ans,a[i]);
printf("%d\n",ans);
}
T10
观察排序用的
函数.
虽然这个
对做题人来说不是非常友好,但是可以稍微思考一下并转化成可看的形式.
bool operator <(const node &c) const {
if (a*c.b==c.a*b) return a<c.a;
return a*c.b<c.a*b;
}
首先return a*c.b<c.a*b
究竟是个什么玩意呢?
我们来看
是怎么比较的.
是不是
的大小比较?
那么这个
函数也是一样的,每一个
表示一个分数,比较的时候按照分数的大小进行排序,把较小的分数放在前面.
如果分数大小相同再按照分子的大小排序.
这样稍微手模一下就可以知道答案.
1 4
1 3
1 2
2 4
2 3
3 4
1 1
2 2
3 3
4 4
4 3
3 2
2 1
4 2
3 1
4 1
T11
1.sz[u]=1,ans[u]=u
2.sz[v]*2>sz[u]
3.sz[ans[u]]*2<sz[u]
4.lj[fa[i]].push_back(i)
5.printf("%d\n",ans[i])
出题人用vector送了很多分.
T12
我们知道一个int
是有
个字节,我们用memset
给它赋值的时候给它的末两位赋了
.
而%08llx
是输出
个位的
进制数.
因此答案就是00003f3f
.
T13
把一个long long
强制转成int
,保留的是后面的位数.
因此答案就是3f3f3f3f
.