码迷,mamicode.com
首页 > 其他好文 > 详细

10.25模拟赛

时间:2018-10-25 14:16:28      阅读:146      评论:0      收藏:0      [点我收藏+]

标签:long   etc   sum   位置   mat   ++   push   noip   n+1   

NP(np)

Description

LYK 喜欢研究一些比较困难的问题, 比如 np 问题。

这次它又遇到一个棘手的 np 问题。 问题是这个样子的: 有两个数 n 和 p, 求 n 的阶乘 对 p 取模后的结果。

LYK 觉得所有 np 问题都是没有多项式复杂度的算法的,所以它打算求助即将要参加 noip 的你, 帮帮 LYK 吧!

Input

? 输入一行两个整数 n,p。

Output

输出一行一个整数表示答案。

数据范围

对于 20%的数据: n,p<=5。

对于 40%的数据: n,p<=1000。

对于 60%的数据: n,p<=10000000。

对于 80%的数据: n<=10^18, p<=10000000。

对于另外 20%的数据: n<=10^18, p=1000000007。

其中大致有 50%的数据满足 n>=p

很显然的是,当\(n \geq p\)的时候,直接输出\(0\)

此时,求解\(n\)的阶乘的时候会乘上一个\(p\)

则代表\(n=k \times p\)

然后呢,其他部分的分怎么得?

分段打表!

我们打出\(10^7\)\(10^9\)部分的阶乘\(%1000000007\)的值.

然后遇到\(p=1000000007\)的情况的时候,我们可以直接跳到这一倍数位置.后面部分暴力扩展即可.

复杂度\(O(能够)\)

还玩了半天\(python\) ~w~

代码

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<queue>
#include<cctype>
#define int long long 
#define R register
using namespace std;
inline void in(int &x)
{
    int f=1;x=0;char s=getchar();
    while(!isdigit(s)){if(s=='-')f=-1;s=getchar();}
    while(isdigit(s)){x=x*10+s-'0';s=getchar();}
    x*=f;
}
int n,p,res=1;
const int fac[]=
{
    1,682498929,491101308,76479948,723816384,67347853,27368307,625544428,199888908,888050723,927880474,281863274,661224977,623534362,
    970055531,261384175,195888993,66404266,547665832,109838563,933245637,724691727,368925948,268838846,136026497,112390913,135498044,217544623,
    419363534,500780548,668123525,128487469,30977140,522049725,309058615,386027524,189239124,148528617,940567523,917084264,429277690,996164327,
    358655417,568392357,780072518,462639908,275105629,909210595,99199382,703397904,733333339,97830135,608823837,256141983,141827977,696628828,
    637939935,811575797,848924691,131772368,724464507,272814771,326159309,456152084,903466878,92255682,769795511,373745190,606241871,825871994,
    957939114,435887178,852304035,663307737,375297772,217598709,624148346,671734977,624500515,748510389,203191898,423951674,629786193,672850561,
    814362881,823845496,116667533,256473217,627655552,245795606,586445753,172114298,193781724,778983779,83868974,315103615,965785236,492741665,
    377329025,847549272,698611116
};
signed main()
{
    freopen("np.in","r",stdin);
    freopen("np.out","w",stdout);
    in(n),in(p);
    if(n>=p){puts("0");return 0;}
    if(p==1000000007)
    {
        int now=n/10000000;
        int res=fac[now];
        for(R int i=now*10000000+1;i<=n;res*=i,res%=p,i++);
        printf("%lld",(res<0)?(res+p)%p:res%p);
        return 0;
    }
    for(R int i=1;i<=n;res*=i,res%=p,i++);
    printf("%lld",(res<0)?(res+p)%p:res%p);
    fclose(stdin);
    fclose(stdout);
    return 0;
}

看程序写结果(program)

Description

LYK 最近在准备 NOIP2017 的初赛, 它最不擅长的就是看程序写结果了, 因此它拼命地 在练习。

这次它拿到这样的一个程序:

Pascal:
readln(n);
for i:=1 to n do read(a[i]);
for i:=1 to n do for j:=1 to n do for k:=1 to n do for l:=1 to n do
if (a[i]=a[j]) and (a[i]<a[k]) and (a[k]=a[l]) then ans:=(ans+1) mod 1000000007;
writeln(ans);
C++:
pcanf(“%d”,&n);
for (i=1; i<=n; i++) scanf(“%d”,&a[i]);
for (i=1; i<=n; i++) for (j=1; j<=n; j++) for (k=1; k<=n; k++) for (l=1; l<=n; l++)
if (a[i]==a[j] && a[i]<a[k] && a[k]==a[l]) ans=(ans+1)%1000000007;
printf(“%d\n”,ans)

LYK 知道了所有输入数据, 它想知道这个程序运行下来会输出多少。

Input

第一行一个数 n, 第二行 n 个数, 表示 ai。

Output

一个数表示答案。

数据范围

数据范围

对于 20%的数据 n<=50。

对于 40%的数据 n<=200。

对于 60%的数据 n<=2000。

对于 100%的数据 n<=100000, 1<=ai<=1000000000

其中均匀分布着 50%的数据不同的 ai 个数<=10, 对于另外 50%的数据不同的 ai 个 数>=n/10。

这题得分最简单了把上面代码粘下来都有40pts

首先你需要离散化.这个看不出来就不怪我了啊

很容易发现,

这题要找满足这个条件的东西数量.
\[ a[i]==a[j] &&a[i]<a[k] &&a[k]==a[l] \]
但是你看它枚举的顺序,先别在乎\(n^4\)

如果\(i==j\)依旧成立.即一个数可以和自己组合.

同时又可以和已经组合过的数组合.

然后如果有\(n\)个数的话,两两组合有多少个方案?建议手玩

\(n \times (n-1) + n\)

\(+n\)即自己和自己组合的方案.

我竟然没看出来是\(n^2\),然后直接写了这个式子.

代码还取了很多模,可丑了

显然现在的答案就是
\[ \sum_{i=1}^{cnt}num_i^2\times \sum_{j=i+1}^{cnt}num_j^2 \]
代码中并不是这样写的.忘了化简式子但是是一样的.

然后我们可以维护一个后缀和,达到\(O(n)\)求解.

总复杂度\(O(nlogn)\)

代码

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<queue>
#include<cctype>
#define N 100008
#define ll long long
#define mod 1000000007
#define R register
using namespace std;
inline void in(int &x)
{
    int f=1;x=0;char s=getchar();
    while(!isdigit(s)){if(s=='-')f=-1;s=getchar();}
    while(isdigit(s)){x=x*10+s-'0';s=getchar();}
    x*=f;
}
int n,a[N],b[N];
int tong[N],mx,cnt=1;
ll ans,sum[N];
int main()
{
    freopen("program.in","r",stdin);
    freopen("program.out","w",stdout);
    in(n);
    for(R int i=1;i<=n;i++)
        in(a[i]),b[i]=a[i];
    sort(b+1,b+n+1);
    for(R int i=2;i<=n;i++)
        if(b[i]!=b[cnt])b[++cnt]=b[i];
    for(R int i=1;i<=n;i++)
    {
        a[i]=lower_bound(b+1,b+cnt+1,a[i])-b;
        (tong[a[i]]+=1)%=mod;
    }
    for(R int i=cnt;i>=1;i--)
        sum[i]=(sum[i+1]%mod+(((tong[i]%mod)*((tong[i]-1)%mod)%mod)*1LL+(tong[i]%mod)*1LL))%mod;
    for(R int i=1;i<cnt;i++)
    {
        R ll tmp=(((tong[i]%mod)*((tong[i]-1)%mod)*1LL)+tong[i])*1LL;
        (ans+=tmp*sum[i+1])%=mod;
    }
    printf("%lld",(ans<0) ? (ans+mod)%mod:ans%mod);
    fclose(stdin);
    fclose(stdout);
    return 0;
}

选数字(select)

Description

LYK 找到了一个 n*m 的矩阵, 这个矩阵上都填有一些数字, 对于第 i 行第 j 列的位置上 的数为 ai,j。

由于它 AK 了 noip2016 的初赛, 最近显得非常无聊, 便想到了一个方法自娱自乐一番。 它想到的游戏是这样的: 每次选择一行或者一列, 它得到的快乐值将会是这一行或者一列的 数字之和。 之后它将该行或者该列上的数字都减去 p(之后可能变成负数)。 如此, 重复 k 次, 它得到的快乐值之和将会是它 NOIP2016 复赛比赛时的 RP 值。

LYK 当然想让它的 RP 值尽可能高, 于是它来求助于你

Input

第一行 4 个数 n,m,k,p。

接下来 n 行 m 列, 表示 ai,j

Output

输出一行表示最大 RP 值

正解贪心.

开两个堆分别维护

  1. \(ansx[i]\)代表在\(n\)行中选择最大值\(i\)次的答案.
  2. \(ansy[i]\)代表在\(m\)列中选择最大值\(i\)次的答案.

然后枚举选\(i\)次行,那么我们就知道选\(k-i\)次列.

但是我们重复减去了一些东西,再加上就好了,应该不是很难理解.就不多BB了

注意极小值一定要够小!!!

代码

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<queue>
#include<cctype>
#define int long long 
#define R register
using namespace std;
inline void in(int &x)
{
    int f=1;x=0;char s=getchar();
    while(!isdigit(s)){if(s=='-')f=-1;s=getchar();}
    while(isdigit(s)){x=x*10+s-'0';s=getchar();}
    x*=f;
}
int n,m,k,p;
int mx=-2147483644666666LL;
int xx[1008],yy[1008];
priority_queue<int>q;
priority_queue<int>Q;
int ansx[1000008],ansy[1000008],ans;
inline int get()
{
    R int res=-2147483644666666LL,pos,flg;
    for(R int i=1;i<=n;i++)
        if(xx[i]>res)res=xx[i]*1LL,flg=1,pos=i;
    for(R int j=1;j<=m;j++)
        if(yy[j]>res)res=yy[j]*1LL,flg=2,pos=j;
    if(flg==1)
    {
        for(R int i=1;i<=m;i++)
            yy[i]-=p;
        xx[pos]-=m*p;
    }
    if(flg==2)
    { 
        for(R int i=1;i<=n;i++)
            xx[i]-=p;
        yy[pos]-=n*p;
    }
    return res;
}
signed main()
{
    freopen("select.in","r",stdin);
    freopen("select.out","w",stdout);
    
    in(n),in(m),in(k),in(p);
    
    if(n<=5 and m<=5 and k<=5)
    {
        for(R int i=1;i<=n;i++)
            for(R int j=1,x;j<=m;j++)
                in(x),xx[i]+=x,yy[j]+=x;
        for(R int i=1;i<=k;i++)ans+=get();
        printf("%lld",ans);
        return 0;
    }//20pts;
    
    
    if(p==0 or k==1)
    {
        for(R int i=1;i<=n;i++)
            for(R int j=1,x;j<=m;j++)
                in(x),xx[i]+=x,yy[j]+=x;
        for(R int i=1;i<=n;i++)mx=max(1LL*xx[i],mx);
        for(R int i=1;i<=m;i++)mx=max(1LL*yy[i],mx);        
        printf("%lld",mx*(k*1LL));
        return 0;
    }//20pts;
    
    
    for(R int i=1;i<=n;i++)
        for(R int j=1,x;j<=m;j++)
            in(x),xx[i]+=x,yy[j]+=x;
    for(R int i=1;i<=n;i++)q.push(1LL*xx[i]);
    for(R int i=1;i<=m;i++)Q.push(1LL*yy[i]);
    for(R int i=1;i<=k;i++)
    {
        R int x=q.top();
        q.pop();
        ansx[i]=ansx[i-1]+x;
        q.push(x-p*m);
        
        R int y=Q.top();
        Q.pop();
        ansy[i]=ansy[i-1]+y;
        Q.push(y-p*n);
    }
    ans=-2147483644666666LL;
    for(int i=0;i<=k;i++)
        ans=max(ans,ansx[i]+ansy[k-i]-i*(k-i)*p);
    printf("%lld",ans);
    fclose(stdin);
    fclose(stdout);
    return 0;
}

10.25模拟赛

标签:long   etc   sum   位置   mat   ++   push   noip   n+1   

原文地址:https://www.cnblogs.com/-guz/p/9848827.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!