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& ...
随机推荐
- Angular.js 入门(一)
最近在学习angular.js,为此方便加深对angular.js前端框架的理解,因此写下这篇angular.js入门 首先介绍下什么是angular.js? AngularJS 是一个 JavaSc ...
- POJ - 2393Yogurt factory
The cows have purchased a yogurt factory that makes world-famous Yucky Yogurt. Over the next N (1 &l ...
- Oracle VM VirtualBOX桥接网卡
1.在VirtualBOX设置中的网络菜单,连接方式选择桥接网卡 2.启动系统,设置静态IP sudo vim /etc/network/interfaces auto enp0s3 ...
- 写在Python学习前
Python是一门非常有意思的语言,不需要太多的语言基础,就可以实现自己想要的操作.许多非计算机专业的学生都可以利用词云分析.分词.画图等实现自己想要的东西.学习Python和学习其他语言一样,需要耐 ...
- 实验吧之【Forms、天网管理系统】
Forms 原题链接 http://ctf5.shiyanbar.com/10/main.php Form 其实是个提示,代表html表单 F12 查看源码,发现 <input name=&qu ...
- 项目代码管理工具Git的总结
在项目的开发中,代码的同步管理很重要,团队的几个人可以通过免费的github管理自己的开源项目代码,高效方便.下面说说,开发中经常用到的git指令操作,基于github平台. 0.配置提交者的账户和邮 ...
- url中常见符号说明
如:http://10.1.1.71:9999/auditcenter/api/v1/auditPlanList?pageSize=20&page=1 ?:分隔实际的url和参数 & ...
- 2.单核CPU是如何实现多进程的?
单核cpu之所以能够实现多进程,主要是依靠于操作系统的进程的调度算法 如时间片轮转算法,在早期,举例说明:有5个正在运行的程序(即5个进程) : QQ 微信 有道词典 网易云 ...
- HDFS概述(一)
HDFS概述(一) 1. HDFS产出的背景及定义 1.1 HDFS产生的背景 随着数据量越来越大,在一个操作系统存不下所有的数据,那么就分配到更多的操作系统管理的磁盘中,但是不方便管理和维护,迫切需 ...
- 【原创】(九)Linux内存管理 - zoned page frame allocator - 4
背景 Read the fucking source code! --By 鲁迅 A picture is worth a thousand words. --By 高尔基 说明: Kernel版本: ...