A
一个环,分成k端,每段的值是所有数|起来,总值是所有端&起来。输出最大值
B
一张有自环、重边的有向图,边的耗时都为1
前k个点有生产机器,每个点j在 x*k+j 时刻产生一个产品(x>=0)
一条路在某刻只有一个产品,路口不限产品数,
问前k个点可以留下那几台机器,使满足所有产品都能被运到第n个点
C
题意
给出n个区间[ s_i , t_i ],问这些区间总覆盖数字多少个
数据范围
n<100, si,ti<365
题解
前缀和维护,然后暴力看一下那些数字有值
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 
 | #include<bits/stdc++.h>using namespace std;
 int const maxn=400;
 int qwq[maxn],sum[maxn];
 int main(){
 int n;
 scanf("%d",&n);
 int a,b;
 for(int i=1;i<=n;i++){
 scanf("%d%d",&a,&b);
 qwq[a]+=1,qwq[b+1]-=1;
 }
 int ans=0;
 for(int i=1;i<=365;i++){
 sum[i]=sum[i-1]+qwq[i];
 if(sum[i]>0)ans++;
 }
 printf("%d\n",ans);
 return 0;
 }
 
 | 
D
题意:
给出一张无向图(可能还有多个连通块),如果1个点感染病毒,他可以感染它邻居的邻居,你可以在一些点之间加边。问最少加几条边可以使最初感染一个点后扩散到所有点都被感染。
题解:
一个连通块内,如果含有一个奇环(环由奇数个点构成),就能感染整个连通块。
所以只要判断图中有几个连通块,有没有一个连通块中含有奇环。先把所有连通块联通,没有奇环的话多花1条边建立奇环。
判断奇环:暴力黑白染色
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 
 | #include<bits/stdc++.h>using namespace std;
 int const maxn=5e5+10;
 int tot,head[maxn],n,m,val[maxn],f[maxn],se[maxn];
 bool vis[maxn];
 struct edge{
 int v,nxt;
 }e[maxn<<1];
 void build(int x,int y){
 e[++tot].v=y;
 e[tot].nxt=head[x];
 head[x]=tot;
 }
 void prime(){
 for(int i=1;i<=n;i++)
 f[i]=i;
 }
 
 int find(int x){
 if(f[x]==x)return f[x];
 f[x]=find(f[x]);
 return f[x];
 }
 
 void merge(int x,int y){
 int f1=find(x),f2=find(y);
 f[f1]=f2;
 }
 bool you=1;
 void ranse(int x){
 vis[x]=1;
 if(you==0)return ;
 for(int i=head[x];i;i=e[i].nxt){
 int v=e[i].v;
 if(vis[v]){
 if(se[x]==se[v]){
 you=0;return ;
 }
 }
 else se[v]=1-se[x];
 }
 for(int i=head[x];i;i=e[i].nxt){
 int v=e[i].v;
 if(!vis[v])ranse(v);
 }
 }
 int main(){
 
 scanf("%d%d",&n,&m);
 prime();
 tot=0;
 memset(head,0,sizeof(int)*(n+5));
 int a,b;
 for(int i=1;i<=m;i++){
 scanf("%d%d",&a,&b);
 build(a,b);
 build(b,a);
 merge(a,b);
 }
 
 int ans=0;
 for(int i=1;i<=n;i++){
 if(find(i)==i){
 ans++;
 ranse(i);
 }
 }
 printf("%d\n", ans-1+you);
 return 0;
 }
 
 | 
E
给n个点,求选3个点,最大的三角形面积。
题解:
凸包+旋转卡壳
F
给定字符串s,可以改变最多k次s中的字符,如果改动后的字符串中出现连着三个或以上的相同字符,这一串字符会变为 * ,问最多让几个字符最后变为 * 。
G
题意
问某个数的非质因子有多少个
题解:
预处理欧拉筛法质因子分解(记录每个数第一次被那个数筛掉),假设一个数x的m个质因子次数分别为 a1,a2....am
ans= (a1+1)*(a2+1)...(am+1)-m
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 
 | #include<bits/stdc++.h>
 using namespace std;
 int const maxn=2000010;
 int prime[maxn],s[maxn];
 int cntprime = 0;
 bool flag[maxn];
 void euler(){
 for (int i = 2; i < maxn; i++){
 if (!flag[i]) prime[++cntprime] = i;
 for (int j = 1; j <= cntprime && prime[j] * i < maxn; j++){
 flag[i * prime[j]] = true;
 s[i*prime[j]]=prime[j];
 if (i % prime[j] == 0)
 break;
 }
 }
 }
 int main(){
 int t;
 scanf("%d",&t);
 int a,b;
 euler();
 for(int i=1;i<=t;i++){
 scanf("%d",&a);
 if(flag[a]==0){
 printf("1\n");
 continue;
 }
 int ans=1,cou=0,v=sqrt(a);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 while(s[a]){
 cou++;
 int tot=0,v=s[a];
 while(a%v==0){
 tot++;
 a/=v;
 }
 ans*=(tot+1);
 }
 if(a>1){ans*=2;cou++;}
 printf("%d\n",ans-cou);
 }
 
 return 0;
 }
 
 | 
比赛:
别暴力质因数分解啊!!
H
给出初始字母s,每个字母有一个替换规则,进行k次替换。
m次询问,问替换完后某个位置的数是多少
l
在r*c的矩形中,选n次子矩形,这些子矩形都至少含有k个相同的格子。问有多少种方案,某一次选的格子不同即为一种不同方案。
J
K
L
在序列中找字典序最小的A B A B
哈哈哈
哈哈哈