初赛练习: 读程序写结果 以及 完善程序 (原创,如有雷同纯属巧合)

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: 将区间 [ l , r ] [l,r] 内的所有数加上 v v .
Q l r. 询问 [ l , r ] [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

t a r j a n . tarjan求最近公共祖先.
给出一棵 n n 个点的树和 m m 组询问,每次询问 u , v u,v 两个点的最近公共祖先.
思想:把询问离线,和询问的编号放在一起,遍历到某一个点的时候把它的询问遍历一遍,如果已经访问过,此时它在并查集中的父亲就是它们俩的最近公共祖先.

#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

, . . , . 如果在一棵树中删掉它的重心,剩下的每一个连通块的大小都不超过原树大小的一半.\newline 求一棵树中每一棵子树的重心.如果有多个重心,输出其中任意一个.
输入格式: 树节点的个数 n n ,询问的个数 q q 每一个节点的父亲, q q 个询问,你需要回答这 q q 个询问,每个询问输出一行.
思路:预处理每一棵子树的重心, O ( 1 ) O(1) 回答询问.
为了简便,树就用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

没有什么目的,仅仅是一个模拟.
由于只有 7 7 个数,求出大于 2 2 的值和 2 2 的最大公约数相加即可.

T2

求字符串中含有"QAQ"子序列的数目.
第一组输入数据是一个乘法原理, 3 × 3 × 3 = 27. 3\times 3\times 3=27.
第二组输入数据暴力分类讨论一下枚举中间 A A 的位置,用左边 Q Q 的个数乘右边 Q Q 的个数, 1 × 4 + 2 × 3 + 2 × 3 + 1 × 4 = 20 1\times4+2\times3+2\times3+1\times4=20 .

T3

按照输入数据模拟一下,我给的模拟复杂度不会太高只有 25 25 .
注意数组会被 s o r t sort 一遍.

T4

观察代码.首先看gpr这个过程,应该是一个线性筛.
然后你会发现主程序里输出了 n = n= ,下面的输出里是 x × y × z × . . . x\times y\times z\times... 的类型.
因此你可以大胆猜想这个代码的目的是分解质因数.
你猜对了.
p [ n ] p[n] 里存储的是什么呢?由于线性筛的特性,每一个数只会被筛到一次.
所以 p [ n ] p[n] 里存储的就是 n n 最小的质因数.
因此按照质因子从小到大的顺序输出 n n 的质因子就可以了.
就是分解的时候算的麻烦一点.
答案就是:

18=2*3*3
1001=7*11*13
30031=59*509
19260817=19260817

输入4就不用我讲了吧.某8位质数你会不知道?

T5

j i c jic 数组是一个阶乘.
i n v inv 数组是一个阶乘逆元的线性递推.
我们要求的公式是 ( 2 n ) ! n ! ( n + 1 ) ! \frac{(2n)!}{n!(n+1)!} .
可以发现,这就求的第 n n 项的卡特兰数.
那么游戏就结束了.

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.
那么要求 [ l , r ] [l,r] 区间内满足什么条件的数呢?
来看 d f s dfs 的五个参数.
根据ans+=dfs(now-1,(yu*10+i)%13,have||le1&&i==3,i==1,lim&&i==da);一句可以看出:
n o w now 表示当前 d f s dfs 到了第几位, y u yu 表示当前模 13 13 的余数, h a v e have 表示当前是否已经出现过 13 13 , l e 1 le1 表示上一个数是不是 1 1 , l i m lim 表示最高位有没有限制.
再根据 n o w = 0 now=0 的判断条件,可以看出我们要求的是模 13 13 等于 0 0 ,并且不含有 13 13 的数.
500 500 1000 1000 中肯定没有含有 13 13 的并且能被 13 13 整除的数.因此我们需要求的就是 500 500 1000 1000 13 13 的倍数,一共 38 38 个.

T9

数据范围是 10 10 ,看似计算量非常大.
仔细思考,可以将该代码转化成以下的形式.
就是说,我们要求 max ( j = 1 i a [ j ] × j + j = i + 1 n a [ j ] × i ) \max(\sum_{j=1}^{i}a[j]\times j+\sum_{j=i+1}^{n}a[j]\times i) ,可以变为求原数组的后缀和的前缀和的最大值的形式,这样只要求 20 20 次,并一眼看出最大值即可.
以下代码和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

观察排序用的 c m p cmp 函数.
虽然这个 c m p cmp 对做题人来说不是非常友好,但是可以稍微思考一下并转化成可看的形式.

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究竟是个什么玩意呢?
我们来看 a b c d \frac{a}{b}和\frac{c}{d} 是怎么比较的.
是不是 a × d b × c a\times d和b \times c 的大小比较?
那么这个 c m p cmp 函数也是一样的,每一个 n o d e node 表示一个分数,比较的时候按照分数的大小进行排序,把较小的分数放在前面.
如果分数大小相同再按照分子的大小排序.
这样稍微手模一下就可以知道答案.

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是有 4 4 个字节,我们用memset给它赋值的时候给它的末两位赋了 0 x 3 f 0x3f .
%08llx是输出 8 8 个位的 16 16 进制数.
因此答案就是00003f3f.

T13

把一个long long强制转成int,保留的是后面的位数.
因此答案就是3f3f3f3f.

猜你喜欢

转载自blog.csdn.net/qq_31908675/article/details/82978016
今日推荐