模拟赛 10-25上午考试记

10-25上午考试记

NP(np)

Time Limit:1000ms Memory Limit:64MB
题目描述
LYK 喜欢研究一些比较困难的问题,比如 np 问题。
这次它又遇到一个棘手的 np 问题。问题是这个样子的:有两个数 n 和 p,求 n 的阶乘
对 p 取模后的结果。
LYK 觉得所有 np 问题都是没有多项式复杂度的算法的,所以它打算求助即将要参加 noip
的你,帮帮 LYK 吧!

打表发现如果n>=p,答案就是0。

所以把n的范围缩小到1e7。但是有p=1e9+7。

分段打表就可以。 段长我设的1000000。

code:

#include <iostream>
#include <cstdio>

#define int long long

using namespace std;

inline int read(){
    int sum=0,f=1; char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();}
    while(ch>='0'&&ch<='9'){sum=(sum<<1)+(sum<<3)+ch-'0'; ch=getchar();}
    return sum*f;
}

int n,p;

int a[117]={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};
/*
时间: 1e7 空间:1e2
*/
signed main(){
    freopen("np.in","r",stdin);
    freopen("np.out","w",stdout);

    n=read(); p=read();
    if(n>=p){
        puts("0");
        return 0;
    }
    if(p==1000000007){
        int zmj=n/10000000;
        int ans=a[zmj];
        for(int i=zmj*10000000+1;i<=n;i++){
            ans=ans*i%p;
        }
        printf("%lld\n",ans%p);
        return 0;
    }
    int ans=1;
    for(int i=1;i<=n;i++){
        ans=ans*i%p;
    }
    printf("%lld\n",ans);

    fclose(stdin);
    fclose(stdout);
    return 0;
}

看程序写结果(program)

Time Limit:1000ms Memory Limit:64MB
题目描述
LYK 最近在准备 NOIP2017 的初赛,它最不擅长的就是看程序写结果了,因此它拼命地
在练习。
这次它拿到这样的一个程序:
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[i]<a[k] && a[k]==a[l]) ans=(ans+1)%1000000007;
printf(“%d\n”,ans);

首先把这段代码复制就有20分。

优化。

把数学式子化简。
\[
ans=\sum_{i=1}^n\sum_{j=1}^n\sum_{k=1}^n\sum_{l=1}^n[a[i]== a[j]  and  a[i]<a[k]  and  a[k]==a[l]]\\=\sum_{i=1}^n\sum_{j=i+1}^n[t[a[i]]*t[a[j]]]\\=\sum_{i=1}^nt[a[i]]*\sum_{j=i+1}^nt[a[j]]
\]
考虑到要开桶,所以去重离散化,一堆令人窒息的操作。

code:

#include <iostream>
#include <cstdio>
#include <algorithm>

#define int long long

using namespace std;

inline int read(){
    int sum=0,f=1; char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();}
    while(ch>='0'&&ch<='9'){sum=(sum<<1)+(sum<<3)+ch-'0'; ch=getchar();}
    return sum*f;
}

const int mod=1000000007;

const int wx=500017;

int js[wx];
int a[wx],b[wx];
int t[wx];
int nxt[wx],pre[wx];

int n;
/*
时间: O(nlogn) 空间: 500000*6 22MB
*/
signed main(){
    freopen("program.in","r",stdin);
    freopen("program.out","w",stdout);

    n=read();
    for(int i=1;i<=n;i++)a[i]=read(),b[i]=a[i];
    sort(b+1,b+1+n);
    int zmj=unique(b+1,b+1+n)-b;
    for(int i=1;i<=n;i++)a[i]=lower_bound(b+1,b+zmj,a[i])-b;
    for(int i=1;i<=n;i++)t[a[i]]++;
    sort(a+1,a+1+n);
    int ans=0;int last=0;
    for(int i=1;i<=n;i++){
        nxt[i]=n+1;
        if(a[i]!=a[i-1]){
            nxt[last]=i;
            last=i;
        }
    }
    last=n+1;
    for(int i=n;i>=1;i--){
        if(a[i]!=a[i+1]){
            pre[last]=i;
            last=i;
        }
    }
    js[a[n]]=0; last=n;
    for(int i=pre[n];i>=1;i=pre[i]){
        js[a[i]]=js[a[last]]+(t[a[last]]*t[a[last]]%mod);
        js[a[i]]%=mod;
        last=i;
    }
    for(int i=1;i<=n;i=nxt[i]){
        ans=(ans+((t[a[i]]*t[a[i]])%mod*js[a[i]])%mod);
        ans%=mod;
    }
    printf("%lld\n",ans%mod);

    fclose(stdin);
    fclose(stdout);
    return 0;
}

选数字 (select)

Time Limit:3000ms Memory Limit:64MB
题目描述
LYK 找到了一个 n*m 的矩阵,这个矩阵上都填有一些数字,对于第 i 行第 j 列的位置上
的数为 ai,j。
由于它 AK 了 noip2016 的初赛,最近显得非常无聊,便想到了一个方法自娱自乐一番。
它想到的游戏是这样的:每次选择一行或者一列,它得到的快乐值将会是这一行或者一列的
数字之和。之后它将该行或者该列上的数字都减去 p(之后可能变成负数)。如此,重复 k
次,它得到的快乐值之和将会是它 NOIP2016 复赛比赛时的 RP 值。
LYK 当然想让它的 RP 值尽可能高,于是它来求助于你。

先无脑暴力。

暴力之后感觉很无力啊。。。

那就贪心吧,最恶心的是行和列混在一起,明显有后效性啊。

那就强行把行和列拆开,分别处理出取i个行或j的最大答案。

还需要合并行和列的情况,那就枚举一个。

可以得到式子:
\[
ans=max(ans,x[i]+y[k-i]-i*(k-i)*q)
\]
为什么要减呢?因为我们处理出x和y两个数组是是互相独立的,也就是我们不考虑另一种情况。

所以这时的\(i\)行,\(k-i\)列都少减了对方所带来的一部分,那么就减去就可以了。

还有一个坑点是ans要附成极小值,中间变量还会炸int。

果然傻人有傻福,我直接\(int  ans=-1e17\)加上\(define  int  long  long\)就无脑过掉了这道题。

code:

#include <iostream>
#include <cstdio>
#include <queue>

#define int long long

using namespace std;

inline int read(){
    int sum=0,f=1; char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();}
    while(ch>='0'&&ch<='9'){sum=(sum<<1)+(sum<<3)+ch-'0'; ch=getchar();}
    return sum*f;
}

const int wx=1500;

priority_queue<int > zmj1;
priority_queue<int > zmj2;

int mp[wx][wx];
int x[wx],y[wx];
int ansx[1000017],ansy[1000017];
int n,m,k,p,ans=-1e17;

void work1(){
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            mp[i][j]=read();
            x[i]+=mp[i][j];
            y[j]+=mp[i][j];
        }
    }
    int maxn=-0x3f3f3f3f;
    for(int i=1;i<=n;i++)maxn=max(maxn,x[i]);
    for(int i=1;i<=m;i++)maxn=max(maxn,y[i]);
    if(k==1)printf("%lld\n",maxn);
    else if(p==0)printf("%lld\n",maxn*k);
    return ;
}

void dfs(int step,int tot){
    if(step==k+1){
        ans=max(ans,tot);
        return ;
    }
    for(int i=1;i<=n;i++){
        int tmp=0;
        for(int j=1;j<=m;j++){
            tmp+=mp[i][j];
            mp[i][j]-=p;
        }
        dfs(step+1,tot+tmp);
        for(int j=1;j<=m;j++)
            mp[i][j]+=p;
    }
    for(int i=1;i<=m;i++){
        int tmp=0;
        for(int j=1;j<=n;j++){
            tmp+=mp[j][i];
            mp[j][i]-=p;
        }
        dfs(step+1,tot+tmp);
        for(int j=1;j<=n;j++){
            mp[j][i]+=p;
        }
    }
}

void work2(){
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            mp[i][j]=read();
        dfs(1,0);
    printf("%lld\n",ans);
} 

void work3(){
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            mp[i][j]=read();
            x[i]+=mp[i][j];
            y[j]+=mp[i][j];
        }
    }
    for(int i=1;i<=n;i++)zmj1.push(x[i]);
    for(int i=1;i<=m;i++)zmj2.push(y[i]);
    for(int i=1;i<=k;i++){
        int tmp=zmj1.top(); zmj1.pop();
        ansx[i]=ansx[i-1]+tmp;
        zmj1.push(tmp-p*m);
        tmp=zmj2.top(); zmj2.pop();
        ansy[i]=ansy[i-1]+tmp;
        zmj2.push(tmp-p*n);
    }
    for(int i=0;i<=k;i++){
        ans=max(ans,ansx[i]+ansy[k-i]-i*(k-i)*p);
    }
    printf("%lld\n",ans);
    return;
}
/*
时间:O(ologn) 空间: 4500000 32MB
*/
signed main(){
    freopen("select.in","r",stdin);
    freopen("select.out","w",stdout);

    n=read(); m=read(); k=read(); p=read();
    if(k==1||p==0){
        work1();
        fclose(stdin);
        fclose(stdout);
        return 0;
    }
    else if(n<=5&&m<=5&&k<=5){
        work2();
        fclose(stdin);
        fclose(stdout);
        return 0;
    }
    else{
        work3();
        fclose(stdin);
        fclose(stdout);
        return 0;
    }

}

总结:

T1考的打表。主要是分段打表看谁用的好吧。。

T2细节蛮多,但是不难。

T3思维题,这几天的考试都告诉我T3不要上来就想比较难的算法,可能那不是正解,要好好思考一下一些基础算法是否适用于这道题,可能基础算法才是正解。

垃圾小呆上午AK,静心等待下午爆炸。。

原文地址:https://www.cnblogs.com/wangxiaodai/p/9848922.html

时间: 2024-10-02 05:09:03

模拟赛 10-25上午考试记的相关文章

潍坊一中模拟赛10.25 长途旅行

[题目描述] JY是一个爱旅游的探险家,也是一名强迫症患者.现在JY想要在C国进行一次长途旅行,C国拥有n个城市(编号为0,1,2...,n - 1),城市之间有m条道路,可能某个城市到自己有一条道路,也有可能两个城市之间有多条道路,通过每条道路都要花费一些时间.JY从0号城市开始出发,目的地为n – 1号城市.由于JY想要好好参观一下C国,所以JY想要旅行恰好T小时.为了让自己的旅行更有意思,JY决定不在任何一个时刻停留(走一条到城市自己的路并不算停留).JY想知道是否能够花恰好T小时到达n

[模拟赛10.12] 老大 (二分/树的直径/树形dp)

[模拟赛10.12] 老大 题目描述 因为 OB 今年拿下 4 块金牌,学校赞助扩建劳模办公室为劳模办公室群,为了体现 OI 的特色,办公室群被设计成了树形(n 个点 n ? 1 条边的无向连通图),由于新建的办公室太大以至于要将奖杯要分放在两个不同的地方以便同学们丢硬币进去开光,OB 想请你帮帮他看看奖杯放在哪两个办公室使得在任意一个在劳模办公室做题的小朋友能最快地找到奖杯来开光. 一句话题意:给出一个 n 个点的树,在两个合适且不同的点放上奖杯,使得每个点到最近的奖杯距离最大值最小. 输入

10.30上午考试

P75竞赛时间: ????年??月??日??:??-??:?? 注意事项(请务必仔细阅读) [ 问题描述] 从1 − ??中找一些数乘起来使得答案是一个完全平方数,求这个完全平方数最大可能是多少.[输入格式]第一行一个数字??.[输出格式]一行一个整数代表答案对100000007取模之后的答案.[样例输入]7[样例输出]144[样例解释]但是塔外面有东西.[数据规模与约定]对于20%的数据, 1 ≤ ?? ≤ 100.对于50%的数据, 1 ≤ ?? ≤ 5000.对于70%的数据, 1 ≤ ?

10.29 上午考试

P73 竞赛时间:????年??月??日??:??-??:?? 题目名称 第二题 死亡 凝视 名称 two death eyesight 输入 two.in death.in eyesight.in 输出 two.out death.out eyesight.out 每个测试点时限 1秒 1秒 1秒 内存限制 512MB 512MB 512MB 测试点数目 10 10 10 每个测试点分值 10 10 10 是否有部分分 无 无 无 题目类型 传统 传统 传统 注意事项(请务必仔细阅读):  

NOIP模拟赛10.07

%hzwer提供试题 http://hzwer.com/7602.html 题目名称 “与” 小象涂色 行动!行动! 输入文件 and.in elephant.in move.in 输出文件 and.out elephant.in move.in 时间限制 1s 1s 1s 空间限制 64MB 128MB 128MB “与” (and.pas/.c/.cpp) 时间限制:1s:空间限制64MB 题目描述: 给你一个长度为n的序列A,请你求出一对Ai,Aj(1<=i<j<=n)使Ai“与”

10.31 上午考试

NP(np)Time Limit:1000ms Memory Limit:64MB题目描述LYK 喜欢研究一些比较困难的问题,比如 np 问题.这次它又遇到一个棘手的 np 问题.问题是这个样子的:有两个数 n 和 p,求 n 的阶乘对 p 取模后的结果.LYK 觉得所有 np 问题都是没有多项式复杂度的算法的,所以它打算求助即将要参加 noip的你,帮帮 LYK 吧!输入格式(np.in)输入一行两个整数 n,p.输出格式(np.out)输出一行一个整数表示答案.输入样例3 4输出样例2数据范

潍坊一中模拟赛10.2 妖精大作战

[Description] 潍坊一中有绿化很好,产生了很多树精草精动物精等妖精,妖王经常安排妖精们打架来消磨时间,其中有N 个妖精开始了一场约架 ,现在每一只妖精都已经把自己所有的弹幕瞄准了一只妖精(有可能是自己). 这些妖精的能力值都非常高,所以一旦将弹幕发射出去,瞄准的妖精必死无疑. 为了使问题变得更有趣一些,妖王打算让这些妖精按照某个顺序来发射弹幕.一旦某个妖精已经被打死了,那么他将退出战斗. 可以预见到,按照不同的顺序,最后死亡的妖精数量是不一样的. 妖王想知道,死亡的妖精数量的最大值和

冲刺CSP-S集训模拟赛总结

开坑.手懒并不想继续一场考试一篇文. 既没必要也没时间侧边栏的最新随笔题解反思相间也丑 而且最近越来越懒了竟然都不写题解了……开坑督促自己写题解. 并不想长篇大论.简要题解也得写啊QAQ. CSP-S模拟赛59 / 2019-10-04上午 要开考了.. 原文地址:https://www.cnblogs.com/xingmi-weiyouni/p/11621307.html

10.30 NFLS-NOIP模拟赛 解题报告

总结:今天去了NOIP模拟赛,其实是几道USACO的经典的题目,第一题和最后一题都有思路,第二题是我一开始写了个spfa,写了一半中途发现应该是矩阵乘法,然后没做完,然后就没有然后了!第二题的暴力都没码QAQ 现在我来写解题报告了,有点饿了QAQ.. 第一题 题目 1: 架设电话线 [Jeffrey Wang, 2007] 最近,Farmer John的奶牛们越来越不满于牛棚里一塌糊涂的电话服务,于 是,她们要求FJ把那些老旧的电话线换成性能更好的新电话线.新的电话线架设 在已有的N(2 <=