20191021考试总结2

第一题:数列

题目描述:对于一个长度为n的数列,第i个数为xi。对于给定的a,b,c找到一个最小的i,使得:
a*(i+1)*x^2+(b+1)*i*x+c+i=0。
输入数据被进行了防离线加密,假设读到a,b,c真实要询问的是a+LastAns,b+LastAns,c+LastAns,对于第一组询问LastAns=0。n<=50000,最多500000组询问。

题解:当化简了N久没有任何规律后。考虑离线操作(来自出题人的误导)。当前a,b,c满足:
0=(a+Lastans) * (i+1) * x^2 + (b+LastAns+1) * i * x + c + LastAns + i = a * (i+1) * x^2+(b+1)* i * x+c+i + ((i+1) * x^2+i+x+1) * LastAns ;通过移项可推出LastAns。

分析:一直在对式子进行各种各样的化简,代换,然后什么也没有发现(。﹏。*),最后知道正解后很震惊(๑→‿ฺ←๑),思维太套路了,瞬间被题目误导,其实他加密的000结束标志就是提示,然而。。。想通了之后代码其实很好码。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=500000+10;
int t;
ll a[N],b[N],c[N],x[N],ans[N];
int main(){
    freopen("seq.in","r",stdin);
    freopen("seq.out","w",stdout);
    scanf("%d",&t);
    for(int i=1;i<=t;i++)
        scanf("%I64d",&x[i]);
    int n=0;
    while(~scanf("%I64d",&a[++n]))
        scanf("%I64d %I64d",&b[n],&c[n]);
    int lst=ans[--n]=-a[n];
    for(int i=n-1;i;i--){
        ll tep=a[i]*(lst+1)*x[lst]*x[lst];
        tep+=(b[i]+1)*lst*x[lst]+c[i]+lst;
        ll ret=((lst+1)*x[lst]*x[lst])+(lst*x[lst]+1);
        lst=ans[i]=-tep/ret;
    }
    for(int i=2;i<=n;i++)
        printf("%I64d\n",ans[i]);
}
/*
5
-2 3 1 -5 2
-5 -4 145
-1 -6 -509
-9 -14 40
-3 -13 21
-3 -3 -3
*/

第二题:刷漆

题目描述:一排栅栏有n块,其中m块前面放了一桶油漆(无限量),一个人在栅栏前随意走动,经过油漆桶时必须蘸漆,路过栅栏时栅栏被染成当前刷子的颜色,问所有栅栏都被染色共有多少情况。

题解:大水题,两个连续的油漆桶(不同颜色)长度相乘。

分析:水题水题水题水题水题水题水题水题

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=100000+10;
const long long mod=1e9+9;
int n,m;char str[3];
pair<int,int> col[N];
int main(){
    freopen("paint.in","r",stdin);
    freopen("paint.out","w",stdout);
    scanf("%d %d",&n,&m);
    for(int i=1;i<=m;i++){
        scanf("%s",str);
        col[i].second=str[0]-64;
        scanf("%d",&col[i].first);
    }
    sort(col+1,col+m+1);
    long long ans=1ll;
    for(int i=2;i<=m;i++)
        if(col[i].second!=col[i-1].second)
            (ans*=(col[i].first-col[i-1].first))%=mod;
    cout<<ans<<endl;
}

第三题:

题目描述:一群妹子,站在数轴上(编号从大到小),给出一些限制,(两个人之间距离最小或最大为多少),求1到n最大距离。

题解:差分约束系统。

分析: spfa()负权环判错了/(ㄒoㄒ)/~~。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
typedef long long ll;
const int N=1000+10;
const int M=100000+10;
const int inf=0x3f3f3f3f;
inline void getint(int&num){
    char c;int flag=1;num=0;
    while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;
    while(c>='0'&&c<='9'){num=num*10+c-48;c=getchar();}
    num*=flag;
}
int n,ml,dl,u,v,c,cnt,dis[N],que[N];
int fir[N],tar[M],nxt[M],w[M];
bool in[N];
queue<int> q;
inline void link(int a,int b,int c){
    tar[++cnt]=b,w[cnt]=c;
    nxt[cnt]=fir[a],fir[a]=cnt;
}
int spfa(int st,int ed){
    memset(in,0,sizeof in);
    memset(que,0,sizeof que);
    memset(dis,0x3f,sizeof dis);
    int inque=1;que[st]=1;
    dis[st]=0,q.push(st);
    while(!q.empty()){
        int t=q.front();q.pop();
        in[t]=0,inque++;
        if(inque>=5*n) return -1;
        for(int i=fir[t];i;i=nxt[i])
            if(dis[tar[i]]>dis[t]+w[i]){
                dis[tar[i]]=dis[t]+w[i];
                if(!in[tar[i]]){
                    in[tar[i]]=1,que[tar[i]]++;
                    q.push(tar[i]);
                    if(que[tar[i]]>n)
                        return -1;
                }
            }
    }
    if(dis[ed]==inf) return -2;
    return dis[ed];
}
int main(){
    freopen("layout.in","r",stdin);
    freopen("layout.out","w",stdout);
    getint(n),getint(ml),getint(dl);
    while(ml--){
        getint(u),getint(v),getint(c);
        link(v,u,c);
    }
    while(dl--){
        getint(u),getint(v),getint(c);
        link(u,v,-c);
    }
    for(int i=1;i<n;i++) link(i,i+1,0);
    printf("%d\n",spfa(n,1));
}
/*
4 2 1
1 3 10
2 4 20
2 3 3
*/

总结:第三题不应该丢分(才整理的模板居然忘了)模板不熟啊啊啊啊啊啊啊啊。。。第一题思维还不够发散,被限制在了常规思维里。(但最后时间没有把握好,暴力都来不及了/(ㄒoㄒ)/~~),这一场发挥得很不好,下一场要更好的计算时间。。。对于想不出的题目要注意转换思维,不要受题目描述误导,认真观察题目中的暗示隐藏信息。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值