首页 > 其他 > 详细

Gym.101955: Asia Shenyang Regional Contest(寒假自训第10场)

时间:2019-02-11 21:37:33      阅读:458      评论:0      收藏:0      [点我收藏+]

C.Insertion Sort

题意:Q次询问,每次给出N,M,Mod,问你有多少种排列,满足前面M个数字排序之后整个序列的LIS>=N-1。

思路:我们把数字看成[1,M],[N-M+1,N]两个部分,假设是A和B。 题意说明最多有一个数字不在自己应该在的位置,那么有三种情况:

1,A在前面,B在后面:贡献是M!;  比如 (1 2, 3 4); (2 1,3 ,4)...

2,A中有一个跑到了后面,剩下的按顺序放:M!* M*(N-M); 比如(1 3, 2 4);  (4 1, 2 3 )...

#include<bits/stdc++.h>
#define ll long long
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=110;
int main()
{
    ll T,N,M,C=0,Mod,ans;
    scanf("%lld",&T);
    while(T--){
        scanf("%lld%lld%lld",&N,&M,&Mod);
        if(M>=N-1){
            ans=1;
            rep(i,1,N) ans=(ll)ans*i%Mod;
        }
        else {
            ans=1; ll t=((N-M)*(N-M-1)+M*(N-M)+1)%Mod; 
            rep(i,1,M) ans=(ll)ans*i%Mod;
            ans=(ll)ans*t%Mod;
        }
        printf("Case #%lld: %lld\n",++C,ans);
    }
    return 0;
}

 

 

G .Best ACMer Solves the Hardest Problem

题意:在二维平面上四种操作: 1,加一个带权的点; 2,删去一个点; 3,给一个点周围欧几里得距离为sqrt(k)的存在的点点权都加w; 4,查询一个到点欧几里得距离为sqrtk的点权和。

思路:发现到一个点的欧几里得距离为k的点并不多。所以我们暴力即可。 注意用 ll。

#include<bits/stdc++.h>
#define ll long long
#define pii pair<int,int>
#define mp make_pair
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxm=10000000;
const int maxn=6010;
ll a[maxn][maxn];int vis[maxn][maxn],Ca,tot;
vector<pii>G[maxm+10];
void init()
{
    rep(i,0,3200){
        rep(j,0,3200){
            if(i*i+j*j>maxm) break;
            G[i*i+j*j].push_back(mp(i,j));
            tot++;
        }
    }
}
void add(int x,int y,int w)
{
    if(vis[x][y]!=Ca) a[x][y]=0,vis[x][y]=Ca;
    a[x][y]+=w;
}
void del(int x,int y)
{
    vis[x][y]=0; a[x][y]=0;
}
void FCY(int x,int y,int w)
{
    if(x<0||x>6000||y<0||y>6000)  return ;
    if(vis[x][y]==Ca) a[x][y]+=w;
}
int query(int x,int y)
{
    if(x<0||x>6000||y<0||y>6000)  return 0;
    if(vis[x][y]==Ca)  return a[x][y];
    return 0;
}
void ADD(int x,int y,int k,int w)
{
    for(int i=0;i<G[k].size();i++){
        int dx=G[k][i].first,dy=G[k][i].second;
        FCY(x+dx,y+dy,w);
        if(dx!=0) FCY(x-dx,y+dy,w);
        if(dy!=0) FCY(x+dx,y-dy,w);
        if(dx!=0&&dy!=0) FCY(x-dx,y-dy,w);
    }
}
ll Query(int x,int y,int k)
{
    ll res=0;
    for(int i=0;i<G[k].size();i++){
        int dx=G[k][i].first,dy=G[k][i].second;
        res+=query(x+dx,y+dy);
        if(dx!=0) res+=query(x-dx,y+dy);
        if(dy!=0) res+=query(x+dx,y-dy);
        if(dx!=0&&dy!=0) res+=query(x-dx,y-dy);
    } return res;
}
int main()
{
    int T,N,M,x,y,w,k,opt;ll ans;
    init();
    scanf("%d",&T);
    while(T--){
        scanf("%d%d",&N,&M); Ca++; ans=0;
        printf("Case #%d:\n",Ca);
        rep(i,1,N){
            scanf("%d%d%d",&x,&y,&w);
            add(x,y,w);
        }
        rep(i,1,M){
            scanf("%d%d%d",&opt,&x,&y);
            x=(x+ans)%6000+1; y=(y+ans)%6000+1;
            if(opt==1){
                scanf("%d",&w);
                add(x,y,w);
            }
            else if(opt==2){
                del(x,y);
            }
            else if(opt==3){
                scanf("%d%d",&k,&w);
                ADD(x,y,k,w);
            }
            else {
                scanf("%d",&k);
                printf("%lld\n",ans=Query(x,y,k));
            }
        }
    }
    return 0;
}

 

K .Let the Flames Begin

题意:约瑟夫问题,给定N,K,M,问第M个出来的人的编号是。 K或者M<1e6;

思路:只要知道公式就大概知道怎么做的题。

我们知道第N个人出来的编号公式是: p=0 ; rep(i,1,N) p=(p+k)%i;    ans=p;(假设从0开始)

而第M个出来的人的编号,我们可以假设已经进行了N-M轮,但其实我们并不关心他们的位置,我可以做完之后把他们放到对应位置即可。

所以第M个人的编号是:p=0;rep(i,1,M) p=(p+k)%(i+N-M);

当M比较小时,可以直接求; 当K比较小时,我们可以利用整除合并的思想做。

#include<bits/stdc++.h>
#define ll long long
#define rep(i,a,b) for(ll i=a;i<=b;i++)
using namespace std;
ll solve(ll N,ll M,ll K) //N个人,每K个skip一次,第M次skip的是谁
{
    if(K==1) return M; ll p=0;
    if(M<=K){
        rep(i,1,M){
            p=(p+K-1)%(i+N-M)+1;
        }
    }
    else {
        ll tM=M;
        rep(i,1,M){
            if(!tM) break;
            if(p+K-1>=i+N-M) tM--,p=(p+K-1)%(i+N-M)+1;//,cout<<i<<":"<<p<<endl;
            else {
                //p+kx-1<i+x-1+N-M   ->  x<(i-1+N-M-p)/(k-1);
                 ll t=(i+N-M-p)/(K-1),g;
                 if((i+N-M-p)%(K-1)==0) t--;
                 g=min(t,tM);
                 p=p+K*g; tM-=g;
                 i=i+g-1;
            }
        }
    }
    return p;
}
int main()
{
    int T,Ca=0; ll N,M,K;
    scanf("%d",&T);
    while(T--){
        scanf("%lld%lld%lld",&N,&M,&K);
        printf("Case #%d: %lld\n",++Ca,solve(N,M,K));
    }
    return 0;
}

 

J .How Much Memory Your Code Is Using?

题意:开了一些变量,问你用了多少内存。

思路:模拟即可。

#include<bits/stdc++.h>
#define ll long long
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=200010;
const int mod=1e9+7;
char c[1000],a[10]={l,o,n,g, ,l,o,n,g};
char b[12]={l,o,n,g, ,d,o,u,b,l,e};
ll sum=0;  int L;
bool check1()
{
    bool F=true;
    if(L<9) return false;
    rep(i,0,8) if(c[i]!=a[i]) return false;
    return true;
}
bool check2()
{
    bool F=true;
    if(L<11) return false;
    rep(i,0,10) if(c[i]!=b[i]) return false;
    return true;
}
void solve()
{
    ll tmp; L=strlen(c);
    if(c[0]==b||c[0]==c) tmp=1;
    if(c[0]==i||c[0]==f) tmp=4;
    if(check1()||c[0]==d) tmp=8;
    if(c[0]==_||check2()) tmp=16;
    rep(i,0,L-1){
        if(c[i]==[){
            int k=0;
            rep(j,i+1,L-1) if(c[j]>=0&&c[j]<=9) k=k*10+c[j]-0;
            tmp*=k;
            break;
        }
    }
    sum+=tmp;
}
int main()
{
    int T,N,Ca=0;
    scanf("%d",&T);
    while(T--){
        scanf("%d\n",&N); sum=0;
        rep(i,1,N){
            gets(c);
            solve();
        }
        ll F=sum/1024;  if(sum%1024) F++;
        printf("Case #%d: %lld\n",++Ca,F);
    }
    return 0;
}

 

Gym.101955: Asia Shenyang Regional Contest(寒假自训第10场)

原文:https://www.cnblogs.com/hua-dong/p/10363254.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!