作为提高组的题,肯定不能像普及组那样一句话题解了。

D1T1——生活大爆炸版石头剪刀布——打个表模拟(好吧,还真是一句话)

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
inline int read(){
    int t=1,num=0;char c=getchar();
    while(c>'9'||c<'0'){if(c=='-')t=-1;c=getchar();}
    while(c>='0'&&c<='9'){num=num*10+c-'0';c=getchar();}
    return num*t;
}
const int f[5][5]={
    {0,0,1,1,0},
    {1,0,0,1,0},
    {0,1,0,0,1},
    {0,0,1,0,1},
    {1,1,0,0,0}
};
int n,na,nb,a[210],b[210],ansa=0,ansb=0;
int main()
{
    n=read();na=read();nb=read();
    for(int i=0;i<na;i++)a[i]=read();
    for(int i=0;i<nb;i++)b[i]=read();
    for(int i=0;i<n;i++){
        int x=a[i%na],y=b[i%nb];
        ansa+=f[x][y];ansb+=f[y][x];
    }
    printf("%d %d",ansa,ansb);
    return 0;
}
View Code

D1T2——联合权值

枚举每个点,只有与它连接的不同的两点对答案有贡献。

这里有一个数学方法,是个很好的优化:

(a+b)^2-a^2-b^2=2ab,(a+b+c)^2-a^2-b^2-c^2=2ab+2ac+2bc,,,,,,,,,

这样就可以简便的求出答案。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#include<queue>
using namespace std;
inline int read(){
    int t=1,num=0;char c=getchar();
    while(c>'9'||c<'0'){if(c=='-')t=-1;c=getchar();}
    while(c>='0'&&c<='9'){num=num*10+c-'0';c=getchar();}
    return num*t;
}
const int maxn=200010,mod=10007;
inline int max(int a,int b){return a>b?a:b;}
vector<int> g[maxn];
int w[maxn],n,ans,sum;
int main()
{
    n=read();
    for(int i=1;i<n;i++){
        int x=read(),y=read();
        g[x].push_back(y);g[y].push_back(x);
    }
    for(int i=1;i<=n;i++)w[i]=read();
    for(int i=1;i<=n;i++){
        int len=g[i].size();
        if(len<2)continue;
        int fi=0,se=0,he1=0,he2=0;
        for(int j=0;j<len;j++){
            int x=g[i][j];
            if(w[x]>se)
                if(w[x]>fi)se=fi,fi=w[x];
                else se=w[x];
            he1+=w[x];he1%=mod;
            he2+=w[x]*w[x];he2%=mod;
        }
        ans=max(ans,fi*se);
        sum+=he1*he1-he2;sum%=mod;
    }
    printf("%d %d",ans,sum);
    return 0;
}
View Code

D1T3——飞扬的小鸟

可真是丧,据说和愤怒的小鸟是cp。

对于上升,我们用完全背包的做法,对于下降,用01背包,超出m的高度特判一下。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
inline int read(){
    int t=1,num=0;char c=getchar();
    while(c>'9'||c<'0'){if(c=='-')t=-1;c=getchar();}
    while(c>='0'&&c<='9'){num=num*10+c-'0';c=getchar();}
    return num*t;
}
const int N=10010,M=1010,INF=1e9;
int n,m,k,up[N],down[N],g[M],f[M],ans=0,t=1;
struct sg{int p,l,h;}s[N];
bool cmp(sg a,sg b){return a.p<b.p;}
inline int min(int a,int b){return a<b?a:b;}
int main()
{
    n=read();m=read();k=read();
    for(int i=1;i<=n;i++)up[i]=read(),down[i]=read();
    for(int i=1;i<=k;i++)
        s[i].p=read(),s[i].l=read(),s[i].h=read();
    sort(s+1,s+1+k,cmp);
    for(int i=1;i<=n;i++){
        for(int j=0;j<=m;j++)
            g[j]=f[j],f[j]=INF;
        int have=0,pass=0;
        if(i-1==s[t].p&&t!=k+1)have=1;
        for(int j=1;j<=m;j++){
            if(j-up[i]>0){
                if((!have)||(j-up[i]>s[t].l&&j-up[i]<s[t].h))
                    f[j]=min(f[j],g[j-up[i]]+1);
                f[j]=min(f[j],f[j-up[i]]+1);
                if(f[j]!=INF)pass=1;
            }
            if(j+up[i]>m){
                if((!have)||(j>s[t].l&&j<s[t].h))
                    f[m]=min(f[m],g[j]+1);
                f[m]=min(f[m],f[j]+1);
                if(f[m]!=INF)pass=1;
            }
        }
        for(int j=m-down[i];j>=1;j--){
            if((!have)||(j+down[i]>s[t].l&&j+down[i]<s[t].h))
                f[j]=min(f[j],g[j+down[i]]);
            if(f[j]!=INF)pass=1;
        }
        if(have){
            if(t<=k)t++;
            if(pass)ans++;
            else{printf("0\n%d",ans);return 0;}
        }
    }
    ans=INF;
    for(int i=1;i<=m;i++)ans=min(ans,f[i]);
    printf("1\n%d",ans);
    return 0;
}
View Code

D2T1——无线网络发射器选址——简单模拟(又是一句话)

倒是我一开始把题目看错了,以为T1巨丧。。

#include<iostream>
#include<cstdio>
using namespace std;
inline int read(){
    int t=1,num=0;char c=getchar();
    while(c>'9'||c<'0'){if(c=='-')t=-1;c=getchar();}
    while(c>='0'&&c<='9'){num=num*10+c-'0';c=getchar();}
    return num*t;
}
int n,d,a[129][129];
inline int max(int x){return x>0?x:0;}
inline int min(int x){return x<128?x:128;}
int check(int x,int y){
    int num=0;
    int l=max(y-d),r=min(y+d),s=max(x-d),t=min(x+d);
    for(int i=l;i<=r;i++)
        for(int j=s;j<=t;j++)
            num+=a[i][j];
    return num;
}
int main()
{
    d=read();n=read();
    for(int i=1;i<=n;i++){
        int x=read(),y=read();a[x][y]=read();
    }
    int ans=1,big=0;
    for(int i=0;i<129;i++){
        for(int j=0;j<129;j++){
            int num=check(i,j);
            if(big==num)ans++;
            if(big<num){ans=1;big=num;}
        }
    }
    printf("%d %d\n",ans,big);
    return 0;
}
View Code

D2T2——寻找道路

好像不是很丧

就先用反向边跑一遍,求出T点不能到的点。

然后枚举一下每一个点,

标记上每个“连向T点不能到的点”的点,包括本身(T点不能到的点)。

然后跑一遍最短路就好了。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#include<queue>
using namespace std;
inline int read(){
    int t=1,num=0;char c=getchar();
    while(c>'9'||c<'0'){if(c=='-')t=-1;c=getchar();}
    while(c>='0'&&c<='9'){num=num*10+c-'0';c=getchar();}
    return num*t;
}
const int N=10010;
vector<int> g[N],f[N];
int n,m,visit[N],no[N],d[N];
void bfs(int t){
    queue<int> q;
    q.push(t);visit[t]=1;
    while(!q.empty()){
        int x=q.front();q.pop();
        for(int i=0;i<f[x].size();i++){
            int y=f[x][i];
            if(!visit[y]){visit[y]=1;q.push(y);}
        }
    }
    for(int i=1;i<=n;i++){
        if(!visit[i]){
            no[i]=1;
            for(int j=0;j<f[i].size();j++)
                no[f[i][j]]=1;
        }
    }
}
void dij(int s){
    for(int i=1;i<=n;i++)d[i]=1e9;
    queue<int>q;
    q.push(s);d[s]=0;
    while(!q.empty()){
        int x=q.front();q.pop();
        for(int i=0;i<g[x].size();i++){
            int y=g[x][i];
            if(d[x]+1<d[y]&&(!no[y])){
                d[y]=d[x]+1;
                q.push(y);
            }
        }
    }
}
int main()
{
    n=read();m=read();
    for(int i=1;i<=m;i++){
        int x=read(),y=read();
        g[x].push_back(y);
        f[y].push_back(x);
    }
    int s=read(),t=read();bfs(t);dij(s);
    printf("%d\n",(d[t]==1e9?-1:d[t]));
    return 0;
}
View Code

D2T3——解方程

 这题感觉挺好骗分的,代码也很好打。

随随便便暴力就30分。

暴力加个随随便便的高精度就50分。

随随便便将a0+a1*k^1+a2*k^2+...+an*k^n(1<=k<=m)取膜就70分。

然后随随便便加个优化——从1循环到mod的大小就100分。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
inline int read(){
    int t=1,num=0;char c=getchar();
    while(c>'9'||c<'0'){if(c=='-')t=-1;c=getchar();}
    while(c>='0'&&c<='9'){num=num*10+c-'0';c=getchar();}
    return num*t;
}
const int mod[5]={14153,19973,33377,11941,20719};
int n,m,num[110];
char a[110][10010];
bool t[1000010];
int main()
{
    n=read();m=read();
    for(int i=0;i<=n;i++)scanf("%s",a[i]);
    for(int k=0;k<5;k++){
        int mo=mod[k];
        memset(num,0,sizeof(num));
        for(int i=0;i<=n;i++){
            int l=strlen(a[i]),f=1;
            if(a[i][0]=='-')f=-1;
            else num[i]=a[i][0]-'0';
            for(int j=1;j<l;j++)
                num[i]=(num[i]*10+a[i][j]-'0')%mo;
            num[i]*=f;
        }
        for(int i=1;i<=mo;i++){
            int sum=0;
            for(int j=n;j>=0;j--)
                sum=(sum*i+num[j])%mo;
            if(sum!=0){
                int j=i;t[j]=1;
                while(j+mo<=m){
                    j+=mo;t[j]=1;
                }
            }
        }
    }
    int ans=0;
    for(int i=1;i<=m;i++)if(!t[i])ans++;
    printf("%d\n",ans);
    for(int i=1;i<=m;i++)
        if(!t[i])printf("%d\n",i);
    return 0;
}
View Code

本文由Yzyet编写,网址为www.cnblogs.com/Yzyet。非Yzyet同意,禁止转载,侵权者必究。

posted on 2017-08-20 20:43  Yzyet  阅读(192)  评论(0编辑  收藏  举报