7.22 NOIP模拟7
又是炸掉的一次考试
T1.方程的解
本次考试最容易骗分的一道题,但是由于T2花的时间太多,我竟然连a+b=c都没判。。暴力掉了40分。
首先a+b=c,只有一组解。
然后是a=1,b=1,答案是c-1,不解释。
对于最大的数据,我们可以用exgcd求出一组特解,之后的通解为x+(b/gcd)*k, y+(a/gcd)*k.
求出正整数解的个数即可。
注意有很多特判,慢慢调试就好(改这题的时间比我改T3的时间都长)
#include<bits/stdc++.h>
#define m 65535
#define int long long
using namespace std;
int t,a,b,c,x,y;
long long ans;
int exgcd(int a,int b,int &x,int &y)
{
if(b==)
{
x=,y=;
return a;
}
int gcd=exgcd(b,a%b,y,x);
y-=(a/b)*x;
return gcd;
}
main()
{
scanf("%lld",&t);
while(t--)
{
ans=;
scanf("%lld%lld%lld",&a,&b,&c);
if(a+b==c&&a>=&&b>=)
{
puts("");
continue;
}
if(a<&&b<&&c<)
a=-a,b=-b,c=-c;
if(a==&&b==)
{
ans=c-;
if(ans>&&ans<=)
{
printf("%lld\n",ans);
continue;
}
if(ans<=)
puts("");
if(ans>m)
puts("ZenMeZheMeDuo");
continue;
}
if(t<=&&a<=&&a>=&&b<=&&b>=&&c>=&&c<=)
{
for(int i=;i<=;i++)
for(int j=;j<=;j++)
{
if(a*i+b*j>c)break;
if(a*i+b*j==c)ans++;
}
if(ans>m)puts("ZenMeZheMeDuo");
else printf("%lld\n",ans);
continue;
}
if(a==&&b==)
{
if(c==)puts("ZenMeZheMeDuo");
else puts("");
continue;
}
if(a==)
{
if(b>)
{
if(c>&&(!(c%b)))puts("ZenMeZheMeDuo");
else puts("");
}
if(b<)
{
if(c<&&(!(c%b)))puts("ZenMeZheMeDuo");
else puts("");
}
continue;
}
if(b==)
{
if(a>)
{
if(c>&&(!(c%a)))puts("ZenMeZheMeDuo");
else puts("");
}
if(a<)
{
if(c<&&(!(c%a)))puts("ZenMeZheMeDuo");
else puts("");
}
continue;
}
if((a<&&b<&&c>=)||(a>&&b>&&c<=))
{
puts("");
continue;
}
if(a<&&b<&&c<)
a=-a,b=-b,c=-c;
int gcd=exgcd(a,b,x,y);
if(c%gcd)
{
puts("");
continue;
}
if(a*b<)
{
puts("ZenMeZheMeDuo");
continue;
}
int k=c/gcd,xx=b/gcd,yy=a/gcd;
x*=k,y*=k;
if(xx<)
xx=-xx,yy=-yy;
if(x<=)
{
int xxx=x/xx+;
x+=xxx*xx,y-=yy*xxx;
}
if(y<=)
{
int xxx=y/yy+;
x-=xx*xxx,y+=yy*xxx;
}
while(x<=)
x+=xx,y-=yy;
while(y<=)
x-=xx,y+=yy;
if(!x||!y)
{
puts("");
continue;
}
if(x/y<||y/x<)
{
puts("");
continue;
}
int aa=x/xx+,bb=y/yy+;
if(!(x%xx))aa--;
if(!(y%yy))bb--;
ans=max(aa,bb);
if(ans>m)puts("ZenMeZheMeDuo");
else printf("%lld\n",ans);
}
return ;
}
T2.visit
本场考试最可惜的一道题,打出正解,却因为答案为0的特判wa(改一个字符,70分->AC)
考试的时候先打了个n^3dp,然后开始找规律
10,5,5 = C(10,5)*C(10,0);
10,4,4 = C(10,5)*C(10,1); 10,4,6=C(10,4)*C(10,0);
10,3,3 = C(10,5)*C(10,2); 10,3,5=C(10,4)*C(10,1); 10,3,7=C(10,3)*C(10,0);
10,2,2 = C(10,5)*C(10,3); 10,2,4=C(10,4)*C(10,2); 10,2,6=C(10,3)*C(10,1); 10,2,8=C(10,2)*C(10,0);
10,1,1 = C(10,5)*C(10,4);
10,0,0 = C(10,5)*C(10,5);
这个表我没有打完,但是我感觉已经很显然了,ans=C(t,(t-n-m)/2)*C(t,(t-n+m)/2);(n>m)
注意特判无解情况,t-n-m为奇数时,必然无解。
然后我终于理解了数据范围最后,mod为若干质数乘积的意思。。。
恩,然后我就开始手推crt,码码码,大概一个小时调完了,和dp对了几个点,感觉没啥问题,没打对拍放心的去看T3了。
考后发现自己打了个这个:
if(((t%(n+m))&))
{
puts("");
return ;
}
???????????我干了啥?把%改成-,AC。一个特判卡掉30分,我。。。。
至于组合数的解释,请参考其他人的题解。(其实是我不会解释)
#include<cstdio>
#include<cmath>
using namespace std;
inline int read(){
register int ss=;register char bb=getchar();
while(bb<||bb>)bb=getchar();
while(bb>=&&bb<=)ss=(ss<<)+(ss<<)+(bb^),bb=getchar();
return ss;
}
inline long long power(long long x,int y,int const mod){
long long ans=;
for(;y;y>>=,x=(x<<)%mod)
if(y&)ans=(ans+x)%mod;
return ans;
}
int const t=read(),p=read();
int n,m,tot;
long long prime[],f[],invv[];
inline void split(long long x,int lit){
for(register int i=;i<=lit && x^;++i)
if(!(x%i))prime[++tot]=i,x/=i;
if(x^)prime[++tot]=x;
return ;
}
long long exgcd(long long a,long long b,long long &x,long long &y){
if(!b)return x=,y=,;
long long z=exgcd(b,a%b,x,y),lh=x;
x=y,y=lh-a/b*y;
return z;
}
inline long long inv(long long x,long long mod){
long long a,b,c=exgcd(x,mod,a,b);
if(c^)return -;
if(a<)a=a%mod+mod;
return a;
}
inline long long cp(long long x,long long y,long long const mod){
if(x<y)return ;
if(!y || x==y)return ;
if(y>x-y)y=x-y;
long long a=,b=;
for(register int i=;i<y;++i)
a=a*(x-i)%mod,b=b*(y-i)%mod;
return a*inv(b,mod)%mod;
}
long long lucas(long long x,long long y,long long mod){
if(x<y)return ;
if(x==y)return ;
return y?cp(x%mod,y%mod,mod)*lucas(x/mod,y/mod,mod)%mod:;
}
inline long long china(){
long long ans=;
for(register int i=;i<=tot;++i)
ans=(ans+power(p/prime[i],power(invv[i],f[i],p),p))%p;
return ans;
}
inline long long cq(int x,int y){
for(register int i=;i<=tot;++i)
f[i]=lucas(x,y,prime[i]);
return china();
}
inline void swap(int &x,int &y){
int z=x;
x=y,y=z;
return ;
}
signed main(){
n=read(),m=read();
if(n<m)swap(n,m);
split(p,sqrt(p));
for(register int i=;i<=tot;++i)
invv[i]=inv(p/prime[i],prime[i]);
printf("%lld",cq(t,t-n+m>>)*cq(t,t-n-m>>)%p);
return ;
}
这是remarkable的代码
T3.光
没想到一道模拟题卡掉了我50分。。。暴力都打错了,骗到20分,考完后发现加clock等一大堆特判可以卡到80分。
正解就是模拟,但是优化了一下。首先,在原来的基础上,可以直接考虑到当前状态的终点:二分。
在同一种状态中,横纵坐标之和或差必然不变,因此我们可以将黑块存进保存坐标之和或差的vector中,给每个vector排序后二分。
但是我们似乎忽略了一个问题:如何统计答案?
一个非常简单却不好想的结论:若一个块被经过,则光线必然只穿过他的一条对角线。
证明如下:
我们给每两个相邻的方块染上不同的颜色,则同一种状态的光线只经过同种颜色的方块。而除了反向反射的两种状态,另外两种反射方式必然从一种颜色的方块变成另一种,即,经过右下->左上对角线和右上->左下对角线的光线穿过的方块颜色必不相同,所以同一方块不可能被穿过两条对角线。
既然如此,那么就又有一个非常显然的结论:一个方块最多被经过两次,两次穿过同一对角线且方向相反。
那么一个方块被经过两次的条件呢?当且仅当发生了反向的反射。同样,若发生了反向的反射,反向光线会将原光线的所有路径重走一遍,因此,一旦发生反向反射,所有被经历的方块都会被穿过两次。否则,每个方块仅被穿过一次。
因此,我们可以记录是否发生了反向的反射,若发生了,最后统计的答案数/2。计算每种状态的贡献时,只需将起始节点和终点的横(纵)坐标相减即可。
注意反射情况十分复杂,分类讨论即可。为了方便,多调几个STL挺好的。
#include<bits/stdc++.h>
#define mk(a,b,c) mp(a,mp(b,c))
#define mp(a,b) make_pair(a,b)
#define pb push_back
using namespace std;
int n,m,k;
long long ans=;
bool v;
vector<int>h[],g[];
map<pair<int,pair<int,int> >,bool>c;
map<pair<int,int>,bool>kk;
int main()
{
scanf("%d%d%d",&n,&m,&k);int kkk=max(n,m);
for(int i=;i<=k;i++)
{
int x,y;
scanf("%d%d",&x,&y);
kk[mp(x,y)]=true;
h[x+y].pb(x-y);
g[x-y+kkk].pb(x+y);
}
for(int i=,x,y;i<=m+;i++)
{
x=,y=i;
kk[mp(x,y)]=true;
h[x+y].pb(x-y);
g[x-y+kkk].pb(x+y);
x=n+;
kk[mp(x,y)]=true;
h[x+y].pb(x-y);
g[x-y+kkk].pb(x+y);
}
for(int i=,x,y;i<=n+;i++)
{
x=i,y=;
kk[mp(x,y)]=true;
h[x+y].pb(x-y);
g[x-y+kkk].pb(x+y);
y=m+;
kk[mp(x,y)]=true;
h[x+y].pb(x-y);
g[x-y+kkk].pb(x+y);
}
for(int i=;i<=kkk+kkk+;i++)
sort(h[i].begin(),h[i].end()),
sort(g[i].begin(),g[i].end());
int x,y,zt,i=;
string ss;
cin>>x>>y>>ss;
if(ss=="NE")zt=;
if(ss=="NW")zt=;
if(ss=="SE")zt=;
if(ss=="SW")zt=;
while(!c[mk(x,y,zt)])
{
c[mk(x,y,zt)]=true;i++;
if(zt==)
{
int cc=*--upper_bound(h[x+y].begin(),h[x+y].end(),x-y),
xx=(x+y+cc)>>,yy=(x+y-cc)>>;
if(i^)ans+=abs(x-xx);
if((kk[mp(xx+,yy)]&&kk[mp(xx,yy-)])
||(!kk[mp(xx+,yy)]&&!kk[mp(xx,yy-)]))
{
zt=,x=xx+,y=yy-;
if(i^)v=true;
}
else if(kk[mp(xx+,yy)])
zt=,x=xx,y=yy-;
else if(kk[mp(xx,yy-)])
zt=,x=xx+,y=yy;
}
else if(zt==)
{
int cc=*upper_bound(h[x+y].begin(),h[x+y].end(),x-y),
xx=(x+y+cc)>>,yy=(x+y-cc)>>;
if(i^)ans+=abs(x-xx);
if((kk[mp(xx-,yy)]&&kk[mp(xx,yy+)])
||(!kk[mp(xx-,yy)]&&!kk[mp(xx,yy+)]))
{
zt=,x=xx-,y=yy+;
if(i^)v=true;
}
else if(kk[mp(xx-,yy)])
zt=,x=xx,y=yy+;
else if(kk[mp(xx,yy+)])
zt=,x=xx-,y=yy;
}
else if(zt==)
{
int cc=*--upper_bound(g[x-y+kkk].begin(),g[x-y+kkk].end(),x+y),
xx=(x-y+cc)>>,yy=(cc-x+y)>>;
if(i^)ans+=abs(x-xx);
if((kk[mp(xx+,yy)]&&kk[mp(xx,yy+)])
||(!kk[mp(xx+,yy)]&&!kk[mp(xx,yy+)]))
{
zt=,x=xx+,y=yy+;
if(i^)v=true;
}
else if(kk[mp(xx+,yy)])
zt=,x=xx,y=yy+;
else if(kk[mp(xx,yy+)])
zt=,x=xx+,y=yy;
}
else if(zt==)
{
int cc=*upper_bound(g[x-y+kkk].begin(),g[x-y+kkk].end(),x+y),
xx=(x-y+cc)>>,yy=(cc-x+y)>>;
if(i^)ans+=abs(x-xx);
if((kk[mp(xx-,yy)]&&kk[mp(xx,yy-)])
||(!kk[mp(xx-,yy)]&&!kk[mp(xx,yy-)]))
{
zt=,x=xx-,y=yy-;
if(i^)v=true;
}
else if(kk[mp(xx+,yy)])
zt=,x=xx,y=yy-;
else if(kk[mp(xx,yy+)])
zt=,x=xx-,y=yy;
}
}
printf("%lld\n",v?ans/:ans);
return ;
}
大模拟
7.22 NOIP模拟7的更多相关文章
- 8.22 NOIP 模拟题
8.22 NOIP 模拟题 编译命令 g++ -o * *.cpp gcc -o * *.c fpc *.pas 编译器版本 g++/gcc fpc 评测环境 位 Linux, .3GHZ CPU ...
- 2018.9.22 NOIP模拟赛
*注意:这套题目应版权方要求,不得公示题面. 从这里开始 Problem A 妹子 Problem B 旅程 Problem C 老大 因为业务水平下滑太严重,去和高一考NOIP模拟,sad... P ...
- 9.22 NOIP模拟题
吉林省信息学奥赛 2017 冬令营 ...
- 2018.08.22 NOIP模拟 string(模拟)
string [描述] 给定两个字符串 s,t,其中 s 只包含小写字母以及*,t 只包含小写字母. 你可以进行任意多次操作,每次选择 s 中的一个*,将它修改为任意多个(可以是 0 个)它的前一个字 ...
- 2021.5.22 noip模拟1
这场考试考得很烂 连暴力都没打好 只拿了25分,,,,,,,,好好总结 T1序列 A. 序列 题目描述 HZ每周一都要举行升旗仪式,国旗班会站成一整列整齐的向前行进. 郭神作为摄像师想要选取其中一段照 ...
- 9.22 noip模拟试题
水灾(sliker.cpp/c/pas) 1000MS 64MB 大雨应经下了几天雨,却还是没有停的样子.土豪CCY刚从外地赚完1e元回来,知道不久除了自己别墅,其他的地方都将会被洪水淹没. CCY ...
- 2018.08.22 NOIP模拟 shop(lower_bound+前缀和预处理)
Shop 有 n 种物品,第 i 种物品的价格为 vi,每天最多购买 xi 个. 有 m 天,第 i 天你有 wi 的钱,你会不停购买能买得起的最贵的物品.你需要求出你每天会购买多少个物品. [输入格 ...
- 2018.08.22 NOIP模拟 or(线段树)
or [描述] 构造一个长度为 n 的非负整数序列 x,满足 m 个条件,第 i 个条件为x[li] | x[li+1] | - | x[ri]=pi. [输入] 第一行两个整数 n,m.接下来 m ...
- 18.9.22 noip模拟赛
此题为找规律.期望100 实际100 #include<cstdio> #include<cstring> #include<iostream> #include& ...
随机推荐
- [开源]如何使用goapp写你的后台管理系统_golang
简析 基于 Gin + GORM + Casbin + vue-element-admin 实现的权限管理系统. 基于Casbin 实现RBAC权限管理. 前端实现: vue-element-admi ...
- java 远程方法调用(RMI)
什么是RMI? 维基百科:一种用于实现远程过程调用的应用程序编程接口.它使客户机上运行的程序可以调用远程服务器上的对象. 什么是序列化及反序列化 (1)序列化:把对象转换为字节序列的过程称为对象的序列 ...
- GUI tkinter (Canvas)绘图篇
from tkinter import * root = Tk()root.title("中国象棋棋盘手绘") can = Canvas(root,width = 400, hei ...
- SQL 存储过程示例讲解
create proc score_result ) --参数 as declare --定义变量@courseNo int, @testTime1 datetime, @avg int begin ...
- JAVA中JDK开发环搭的搭建,jvm jre
1.JDK的下载与安装: www.oracle.com 安装需要注意的是:不能把jdk安装到有空格或中文的文件夹中,建议大家在某个目录下创建一个JavaWeb的文件夹,然后把所学的java所有内容(后 ...
- 【C语言笔记】#define与typedef的区别
1.#define define是预处理指令,在编译时不进行任何检查,只进行简单的替换 宏定义的一般形式为: #define 宏名 字符串 这里所说的字符串是一般意义上的字符序列,不要和C语言中的字符 ...
- 那些你不知道的HTML知识,快来学习一下吧
前言 HTML作为前端三大基础知识点之一,是每一个前端开发人员都要掌握的部分.今天这篇文章我们来看看一些平时不太会注意,却在面试时可能会问到的题目,来看看你都会吗? 如何使用div模拟实现textar ...
- Linux提权中常见命令大全
在拿到一个 webshell 之后,大家首先会想到去把自己的权限提升到最高,windows 我们会提升到 SYSTEM 权限,而 Linux 我们会提升到 root 权限,拿在进行 Linux 提权的 ...
- Python3的编码整理总结
python3在内存中是用unicode编码方式存储的,所以不能直接储存和传输,要转化为其他编码进行储存和传输. 字符串通过编码转换成字节码,字节码通过解码成为字符串 encode:str --> ...
- [LUOGU1272] 重建道路 - 树形背包
题目描述 一场可怕的地震后,人们用N个牲口棚(1≤N≤150,编号1..N)重建了农夫John的牧场.由于人们没有时间建设多余的道路,所以现在从一个牲口棚到另一个牲口棚的道路是惟一的.因此,牧场运输系 ...