Codeforces ---- Hello 2020

哈哈哈,tourist挂终测了,rank4了,莫名开心哈哈哈。

我没有挂终测,我蓝了!!哈哈哈哈,好久好久没打了,真是没有想到,打的那么难受,竟然没挂终测,还蓝了,哈哈哈哈

---------------------------------------------------------

哇,hello 2019感觉一点也不友好。。。B题好烦人的赶脚,一直想歪。。。怕是蓝不了?

这次回到大号,以后也一直打大号了,不开小号玩了。。

传送门:http://codeforces.com/contest/1284

A. New Year and Naming

这个很简单,类似怎国家的甲乙丙丁。。。子丑寅卯。。。来对应年份。

取个余输出就完事。。相信不会有人不会

 

#include<bits/stdc++.h>
#define ll long long
#define INF 0x3f3f3f3f3f3f3f3fLL
#define inf 0x3f3f3f3f
#define maxn 100010
using namespace std;
int a[maxn],n,m,x,y,z,T,c,v;
char ch[25][maxn],chh[25][maxn];
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
    {
        scanf("%s",ch[i]);
    }
    for(int i=1;i<=m;i++)
    {
        scanf("%s",chh[i]);
    }
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&x);
        c=x%n;
        v=x%m;
        if(c==0) c=n;
        if(v==0) v=m;
        printf("%s%s\n",ch[c],chh[v]);
    }
 
    //if() printf("YES\n");
    //else printf("NO\n");
}

B. New Year and Ascent Sequence

题意:定义ascent :序列a,存在正序对,即1<i<j<n,有ai<aj.

给定n个序列,求n个序列两两组合的n^2个组合序列中,有多少ascent序列。。

思路:一开始暴力一发,想着暴力出奇迹!然后就T+1..然后就转弯去做C了,C简单。再回来做B,做了一个小时+。也是醉了!!

然后慢慢想,把自己成功过绕进去了。。最后,幸好做出来了,不然就凉透了!!!

反向思维,ascent序列数量=n^2 - 非ascent序列数量。

而非ascent序列比较有规律,就是两个序列单调不增,且连接起来,还是单调不增的。所以可以将这样的单调序列找出来,pos存下最大最小值,vis[i] = pos内的序列中,最小值<=i的个数。

最后对每一个pos内的序列考虑,可以与他连接拼成非ascent序列的序列。

代码:

#include<bits/stdc++.h>
#define ll long long
#define INF 0x3f3f3f3f3f3f3f3fLL
#define inf 0x3f3f3f3f
#define maxn 100010
using namespace std;
ll ans;
struct AA
{
    ll l,r;
    bool operator <(const AA&a)const
    {
        if(l==a.l) return r<a.r;
        return l<a.l;
    }
}pos[maxn];
ll a[maxn],x,T,num;
ll n;
ll minn,maxx,ok,vis[maxn*10],dis[maxn*10];
int main()
{
    ans=0;num=0;
    scanf("%lld",&n);
    for(int i=1;i<=n;i++)
    {
        minn=0x3f3f3f3f;
        maxx=-0x3f3f3f3f;
        scanf("%lld",&x);ok=0;
        for(int j=1;j<=x;j++)
        {
            scanf("%lld",&a[j]);
            if(ok) continue;
            minn=min(minn,a[j]);
            maxx=max(maxx,a[j]);
            if(j>1)
            {
                if(a[j]>a[j-1]) ok=1;
            }
        }
        if(!ok)
        {
            pos[++num].l=minn;
            pos[num].r=maxx;

        }
    }
    sort(pos+1,pos+1+num);
    int tt=1;
    for(int i=0;i<=1000000;i++)
    {
        if(i) vis[i]=vis[i-1];
        while(tt<=num&&i==pos[tt].l)
        {
            vis[i]++;
            tt++;
        }
    }
    for(int i=1;i<=num;i++)
    {
        ans+=(num-vis[pos[i].r-1]);
    }
    printf("%lld\n",n*n-ans);
}

C. New Year and Permutation

题意:定义framed segment :区间[l,r],max值-min值=r-l;求有1-n组成的n!个序列中,所有framed segment的个数%m

思路:因为max-min=r-l,可以想见,区间[l,r]内的r-l+1个数正好是min~max这max-min+1个数的任意组合,

其实就是个组合数的题,列公式呗,然后还发现不用组合数直接能求,都是C(x,1)模式的组合数。只需要求阶乘就可以~

令framed segment 的区间长度l取值从1~n。长度为n的区间中有C(n-l+1,1)个连续的长度为l的区间可以选。区间可以选择C(n-l+1,1)种连续的序列。来存放,然后区间[l,r]内全排列l!,外部全排列(n-l)!,全部×起来就是长度为l的framed segment 的个数。

按这步骤,解一下n=3的情况,就很好理解了。

代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll MAXN=262144+5;
ll a[MAXN],mod,n;
ll fact[MAXN],ifact[MAXN];//fact[i]是i的阶乘,ifact[i]是阶乘的除法逆元,两者用于求组合数
ll pow_mod(ll n,ll k,ll mod) //快速幂求n^k余m的结果
{
    ll res=1;
    n=n%mod;
    while(k>0)
    {
        if(k&1)
            res=res*n%mod;
        n=n*n%mod;
        k>>=1;
    }
    return res;
}
void init()//初始化
{
    fact[0]=ifact[0]=1;
	for(int i=1;i<=n;++i)
    {
        fact[i]=(fact[i-1]*i)%mod;
		ifact[i]=pow_mod(fact[i],mod-2,mod);
	}
}
ll C(ll n,ll m)//求组合数
{
    if(n<m||m<0)
        return 0;
    return  fact[n]*ifact[m]%mod*ifact[n-m]%mod;
}
ll ans,t;
int main()
{
 
 
    while(scanf("%lld%lld",&n,&mod)!=EOF)
    { init();ans=0;
        for(int l=1;l<=n;l++)
        {
            t=(n-l+1)*(n-l+1)%mod;
            ans+=(t*fact[l]%mod)*(fact[n-l])%mod;
            ans%=mod;
            //cout<<l<<" "<<ans<<endl;
        }
        printf("%lld\n",ans);
    }
    return 0;
}

 D题暴力没有奇迹!!!T,再见!!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值