[NOIP2014] Zhentiレビュー

トピックリンク

じゃんけんのビッグバンのバージョンがシミュレーションで、言うことはありません。

ユナイテッドの重みはライン上で、統計それを任意の関節の重み2人の息子、統計および最大合計メンテナンスを各点を列挙します

私は鳥DP良い質問フライング、DPを使用して考えることは困難ではない[i] [j]は、i番目の行に到達するためにクリックの最小数を表し、高さのJ、直接列挙、jは次の列意志TLE、必要の位置に移送しました最適化

#include<iostream>
#include<cstring>
#include<cstdio>
#define min(x,y) ((x)<(y)?(x):(y))
#define max(x,y) ((x)>(y)?(x):(y))
using namespace std;

const int N=10010;
const int M=2010;
const int INF=100000;

const int ch_top=4e7+3;
char ch[ch_top],*now_r=ch-1;
inline int read(){
    while(*++now_r<'0');
    register int x=*now_r-'0';
    while(*++now_r>='0')x=x*10+*now_r-'0';
    return x;
}

int n,m,k,X[N],Y[N],cnt[N],s[N],num;
int dp[N][M],low[N],high[N],Max;

int main()
{
//  freopen("a.in","r",stdin);
    fread(ch,1,ch_top,stdin);
    n=read(); m=read(); k=read();
    for(int i=0;i<n;++i){
        X[i]=read(); Y[i]=read();
        low[i]=1; high[i]=m;
    }
    low[n]=1; high[n]=m;
    int P,L,H;
    while(k--){
        P=read(); L=read(); H=read();
        low[P]=L+1; high[P]=H-1;
        ++cnt[P];
    }
    for(int i=1;i<=n;++i)
        cnt[i]+=cnt[i-1];
    for(int i=0;i<=n;++i)
        for(int j=0;j<=m;++j)
            dp[i][j]=INF;
    for(int i=1;i<=m;++i)
        dp[0][i]=0;
    for(int i=0;i<n;++i){
        num=0;
        for(int j=high[i];j>=low[i];--j)//从上往下依次转移,有利于后面优化时间
          if(dp[i][j]<INF){//先转移向上跳的情况 
            s[++num]=j;
            Max=max(Max,i);
            int g=(low[i+1]-j)/X[i];//直接计算需要向上跳几次达到low[i+1]
            if(g<1) g=1;
            int h=j+g*X[i];
            if(h<low[i+1]) ++g,h+=X[i];
            while(h<=high[i+1]){
                if(dp[i+1][h]>dp[i][j]+g)
                    dp[i+1][h]=dp[i][j]+g;
                else break;//优化时间,如果dp[i+1][h]已经有了更好的方案,一定是向上跳了若干步后转移过来的,那么dp[i+1][h+k*X[i]]也可以被跳到
                ++g; h+=X[i];
            }
            if(high[i+1]==m)
                dp[i+1][m]=min(dp[i+1][m],dp[i][j]+(m-j)/X[i]+1);//计算到天花板的步数并转移
        }
        for(int l=1,j=s[l];l<=num;j=s[++l]) //后转移向下落的情况 
          if(dp[i][j]<INF){
            int t=j-Y[i];
            if(low[i+1]<=t&&t<=high[i+1])
                dp[i+1][t]=min(dp[i+1][t],dp[i][j]);
        }
    }
    int ans=INF;
    for(int i=low[n];i<=high[n];++i)
        if(dp[n][i]<INF)
            ans=min(ans,dp[n][i]);
    if(ans<INF){
        puts("1");
        printf("%d\n",ans);
        return 0;
    }
    puts("0");
    printf("%d\n",cnt[Max]);
    return 0;
}

どのように暴力の暴力だと思う方法についてのWi-Fiトランスミッターサイト

最初のエンドポイントをマークし、通信しているポイントの側とエンドポイントのすべての点をマークし、最終的にはライン上の最短を見つけることがすべてできるの質問の意味に従ってあなたの方法を見つけます

この問題は、我々は法と大きな素数はまだ0になった後、元の式は、0と評価された場合、元の式を使用して、複数の剰余を使用し、大きな素数の結果であることがわかった、高性能爆薬が可能と直接方程式を解決します得られた結果も0ですので、あなたが立ち往生している場合がありますが、トピックはまだ998244353 19260817 19491001以上または2147483647である方法を知っています

また、無秦九韶と時間の計算は、O(n)のですが、私はこの事を使用するかわかりません。..

#include<iostream>
#include<cstring>
#include<cstdio>
#define int long long
using namespace std;

const int MAXN=110;
const int MAXM=1000010;
const int MOD=2147483647;

int n,m,a[MAXN];

inline int read(){
    int x=0,f=1; char c=getchar();
    while(c<'0') { if(c=='-') f=-1; c=getchar();}
    while(c>='0') x=(x*10+c-'0')%MOD,c=getchar();
    return x*f;
}

int cnt,ans[MAXM];

inline bool check(int x){
    int ans=0,y=1;
    for(int i=0;i<=n;++i){
        ans=(ans+a[i]*y)%MOD;
        y=y*x%MOD;
    }
    return ans==0;
}

signed main()
{
    scanf("%lld%lld",&n,&m);
    for(int i=0;i<=n;++i)
        a[i]=read();
    for(int i=1;i<=m;++i)
        if(check(i)) ans[++cnt]=i;
    printf("%lld\n",cnt);
    for(int i=1;i<=cnt;++i)
        printf("%lld\n",ans[i]);
    puts("");
    return 0;
}

おすすめ

転載: www.cnblogs.com/yjkhhh/p/11635351.html