版权声明:转载请注明原出处啦(虽然应该也没人转载): https://blog.csdn.net/hzk_cpp/article/details/82079463
T1:
题目大意:给出一个人的每门课的成绩排名,求这个人总成绩的最大排名和最小排名.
开始看的时候想这道题感觉这道题很懵啊,觉得总排名跟各科排名没什么关系啊.
突然如果只要有一门课的成绩比另一个人低,就有可能总成绩比那个人低...
所以代码如下:
#include<bits/stdc++.h>
using namespace std;
#define Abigail inline void
typedef long long LL;
const int N=1000;
int n,m,a[N+9],su,sd;
Abigail into(){
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++)
scanf("%d",&a[i]);
}
Abigail work(){
for (int i=1;i<=n;i++)
su+=a[i]-1,sd+=m-a[i];
}
Abigail outo(){
if (sd>=m) printf("1\n");
else printf("%d\n",m-sd);
if (su>=m) printf("%d\n",m);
else printf("%d\n",su+1);
}
int main(){
freopen("rank.in","r",stdin);
freopen("rank.out","w",stdout);
into();
work();
outo();
return 0;
}
T2:
题目大意:给定一张有向图,每个节点只有一条出边,现在要求每个节点开始的最长链(简单路径)长度,其中所有边的边权都为正数.
感觉这道题跟NOIP2015信息传递很像啊,于是就把环先找出来打上标记,算出每个环的和,然后记忆化搜索就可以了.
考场上还剩半个小时的时候拍出问题也是恐怖.
代码如下:
#include<bits/stdc++.h>
using namespace std;
#define Abigail inline void
typedef long long LL;
const int N=200000;
struct node{
int to,v,c,ans;
}d[N+9];
int sum[N+9],n,num,top,t[N+9];
int dfs(int k){
if (t[k]&&t[k]^top) return 0;
if (t[k]==top) {
d[k].c=++num;
return num;
}
t[k]=top;
int now=dfs(d[k].to);
if (d[k].c) return 0;
else {
d[k].c=now;
return now;
}
}
int dfs1(int k){
if (d[k].ans) return d[k].ans;
t[k]=1;
if (d[k].c) {
d[k].ans=sum[d[k].c];
return d[k].ans;
}
d[k].ans=d[k].v+dfs1(d[k].to);
return d[k].ans;
}
Abigail into(){
scanf("%d",&n);
for (int i=1;i<=n;i++)
scanf("%d",&d[i].v);
for (int i=1;i<=n;i++)
scanf("%d",&d[i].to);
}
Abigail work(){
for (int i=1;i<=n;i++)
if (!t[i]) top++,dfs(i);
for (int i=1;i<=n;i++)
sum[d[i].c]+=d[i].v;
for (int i=1;i<=n;i++)
t[i]=0;
for (int i=1;i<=n;i++)
if (!d[i].ans) dfs1(i);
}
Abigail outo(){
for (int i=1;i<=n;i++)
printf("%d\n",d[i].ans);
}
int main(){
freopen("travel.in","r",stdin);
freopen("travel.out","w",stdout);
into();
work();
outo();
return 0;
}
T3:
题目大意:给出一个字符串长度为n,只包含前k个小写字母,现在在加上m个字符(也是前k个小写字母),使得字符串中不同的子序列最多,求最多的子序列的数量,对取模.
考场写了个分段拿分,一个是k=1的情况(要算上空串),另一个是5进制压位暴力,然后5进制压位暴力没有乘5...
代码如下:
#include<bits/stdc++.h>
using namespace std;
#define Abigail inline void
typedef long long LL;
const LL mod=1000000007;
const int N=1000000;
LL sum,f[N+9],ans[26];
int n,m,k,e[N+9],p[N+9],top,get[N+9],t;
bool use[10000000];
char c[N+9];
Abigail into(){
scanf("%d%d",&m,&k);
scanf("%s",&c);
n=strlen(c);
}
int power(int a,int b){
int s=1;
for (int i=1;i<=b;i++)
s=s*5;
return s;
}
void check(){
int s=0,l=0;
for (int i=0;i<=(1<<n+m)-1;i++){
l=0;
for (int j=0;j<n+m;j++)
if (1<<j&i) l=l|1<<j;
if (!use[l]) s++,get[++t]=l,use[l]=1;
}
if (s>sum) sum=s;
}
void dfs1(int k){
if (n+k>n+m){
check();
for (int i=1;i<=t;i++)
use[get[i]]=0;
return;
}
for (int i=0;i<5;i++){
e[i]=i;
dfs1(k+1);
}
}
Abigail work1(){
for (int i=0;i<n;i++)
e[i+1]=c[i]-'a';
dfs1(n+1);
}
Abigail work2(){
sum=1LL*(n+m+1);
}
Abigail outo(){
printf("%lld\n",sum);
}
int main(){
freopen("string.in","r",stdin);
freopen("string.out","w",stdout);
into();
if (k==1) work2();
else if (n<=5&&m<=5&&k<=5) work1();
outo();
return 0;
}
正解是一个DP,先来看m=0的情况,这个时候不用增加字符,只要求出子序列个数就可以了.
那么我们设f[i]表示到第i个字符必须包括第i个字符的不同子序列的个数.
那么我们发现若直接用会出现一个问题,就是会有重复,那我们在记录一个last[i]表示跟第i个字符相同的上一个出现的位置,那我们再推的时候减掉一个F[last[i]-1]及之前的就可以了.
也就是说公式变成,用前缀和优化就可以了.
但是我们应该在后面加入什么字符呢?
我们设g[i]为f[i]的前缀和数组,那么f[i]=g[i-1]-g[last[i]-1],那么我们可以知道下一次转移的时候我们肯定要让f[i]最大,所以我们要让last[i]-1最小.
那么时间复杂度,空间复杂度.
代码如下:
#include<bits/stdc++.h>
using namespace std;
#define Abigail inline void
typedef long long LL;
const LL mod=1000000007LL;
const int N=1000000;
const LL INF=1LL<<61;
int n,m,k;
LL f[N*2+9],a[N*2+9],last[27],g[N*2+9];
char c[N*2+9];
Abigail into(){
scanf("%d%d",&m,&k);
scanf("%s",c+1);
n=strlen(c+1);
}
Abigail work(){
for (int i=1;i<=n;i++)
a[i]=c[i]-'a'+1LL;
for (int i=1;i<=n;i++){
if (last[a[i]]<1) f[i]=(g[i-1]+1)%mod;
else f[i]=(g[i-1]+mod-g[last[a[i]]-1])%mod;
g[i]=(f[i]+g[i-1])%mod; //这里的g[i]是表示f[i]的前缀和-f[last[i]-1]的前缀和
last[a[i]]=i; //这里的last[i]是表示字符i上一次出现的位置
}
for (int i=n+1;i<=n+m;i++){
LL e=0,mi=INF;
for (int j=1;j<=k;j++)
if (mi>last[j]) mi=last[j],e=j;
a[i]=e; //找到最小的last[i]-1并加入这个i字符
if (last[a[i]]<1) f[i]=(g[i-1]+1)%mod;
else f[i]=(g[i-1]+mod-g[last[a[i]]-1])%mod;
g[i]=(f[i]+g[i-1])%mod;
last[a[i]]=i;
}
}
Abigail outo(){
printf("%lld\n",(g[n+m]+1>=mod)?g[n+m]+1-mod:g[n+m]+1);
}
int main(){
freopen("string.in","r",stdin);
freopen("string.out","w",stdout);
into();
work();
outo();
return 0;
}