2021牛客多校8---ADEK

A Ares, Toilet Ares 点击查看 1050/5067 通过

在这里插入图片描述
题意:
这题的题意就是厕所启发灵感哈哈哈
49-33
思路:
这里就是a+Πpi,pi就是成功概率相乘,但这里要分数取模+求逆元作除法

♡ \heartsuit 分数取模!

我们如果要求这个式子------- 1 a \frac{1}{a} a1 m o d mod mod p p p
我们可以根据费马小定理

在这里插入图片描述

所以就可以把 1 a \frac{1}{a} a1 m o d mod mod p p p转化成 a p − 2 a^{p-2} ap2 m o d mod mod p p p
如果分子不是1,那么就 m ∗ a − 1 m*a^{-1} ma1 m o d mod mod p p p = = = ( m (m (m m o d mod mod p ) p) p) ∗ * ( a − 1 (a^{-1} (a1 m o d mod mod p ) p) p) m o d mod mod p p p
其中m为素数,如果m过大,可以用快速求正整数幂

然后他的代码有点像快速幂,可以给你们对比一下

分数取模代码

long long fast_mod(long long a,long long b) {
	long long r = 1;
	a %= mod;
	while (b) {
		if (b & 1) r = (r*a) % mod;
		a = (a*a) % mod;
		b >>= 1;
	}
	return r;
}

快速幂代码

long long fastPower(long long base, long long power) {
    long long result = 1;
    while (power > 0) {
        if (power & 1) //此处等价于if(power%2==1)
            result = result * base % 1000;
        power >>= 1;//此处等价于power=power/2
        base = (base * base) % 1000;
    }
    return result;
}

取模的运算规则

模运算与基本四则运算有些相似,但是除法例外。
其规则如下:
(a + b) % p = (a % p + b % p) % p
(a - b) % p = (a % p - b % p) % p
(a * b) % p = (a % p * b % p) % p
a ^ b % p = ((a % p)^b) % p
结合律:
((a+b) % p + c) % p = (a + (b+c) % p) % p
((ab) % p * c)% p = (a * (bc) % p) % p
交换律:
(a + b) % p = (b+a) % p
(a * b) % p = (b * a) % p
分配律:
(a+b) % p = ( a % p + b % p ) % p
((a +b)% p * c) % p = ((a * c) % p + (b * c) % p) % p

逆元

当求解公式:(a/b)%m 时,因b可能会过大,会出现爆精度的情况,所以需变除法为乘法:

设c是b的逆元,则有b*c≡1(mod m);

( a / b ) (a/b) (a/b) m o d mod mod m m m = = = ( a / b ) (a/b) (a/b) ∗ 1 *1 1 m o d mod mod m m m = = = ( a / b ) ∗ b (a/b)*b (a/b)b ∗ * c c c m o d mod mod m m m= a a a ∗ * c c c ( m o d (mod (mod m ) m) m);

即a/b的模等于a*(b的逆元)的模;

const int mod = 1000000009;
long long quickpow(long long a, long long b) {
    if (b < 0) return 0;
    long long ret = 1;
    a %= mod;
    while(b) {
        if (b & 1) ret = (ret * a) % mod;
        b >>= 1;
        a = (a * a) % mod;
    }
    return ret;
}
long long inv(long long a) {
    return quickpow(a, mod - 2);
}

最后一个知识点:负数取模变正数

(a % b + b) % b

代码1:

#include<bits/stdc++.h>


using namespace std;

typedef long long LL;
const LL mod = 4933;


LL pows(LL a, LL x, LL p)
{
    if(x==0)return 1;
    LL t = pows(a, x>>1,p);
    if(x%2==0)return t*t%p;
    return t*t%p*a%p;
}
LL inv(LL x, LL p)
{
    return pows(x,p-2,p);
}

int main()
{
    LL n,m,k,a,l;
    cin>>n>>m>>k>>a>>l;
    LL ans = 1;
    for(int i=1; i <= k; i++)
    {
        int x, y, z;
        cin>>x>>y>>z;
        if(x!=0)//这是这一道题的唯一坑点就是如果x=0
            (ans *= (1-y*inv(z,mod)%mod+mod)%mod)%=mod;
    }
    ans = (ans+a)%mod;//(ans+a%mod+mod)%mod;
    cout<<ans<<endl;
    return 0;
}

代码2:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

const int N=1e5+10;
const ll mod=4933;

ll ny(ll a,ll k,ll mod){ 
    ll res=1;
    while(k){
        if(k&1) res=(ll)res*a%mod;
        a=(ll)a*a%mod;
        k/=2;
    }
    return res;
}




int main()
{
	int flag=0;
	ll n,m,k,a,l;
	
	cin>>n>>m>>k>>a>>l;
    ll ans=1;
// 	if(n==a){
// 		cout<<a%mod<<endl;
// 		return 0;
// 	}
	for(int i=1;i<=k;i++){
		ll x,y,z;
		cin>>x>>y>>z;
		if(x!=0){
			if(y==z){
				flag=1;
			}else{
                ans=(ans*((z-y)*ny(z,mod-2,mod)%mod))%mod;
			}
		}
	}
	if(flag){
		cout<<a%mod<<endl;
	}else{
		cout<<(ans+a)%mod<<endl;
	}

	return 0;
}

wa了几次就是因为没有每一步都mod,这种取模的题不是第一次在牛客中出现,就再碰到类似的题的话,自己写的完全对也很难,所以,多看多思考!

♡ \heartsuit D OR 点击查看 937/4152 通过

在这里插入图片描述
在这里插入图片描述
输入

4
7 5 5
7 9 5

输出

2

与运算规则

0&0=0;0&1=0;1&0=0;1&1=1
即:两个同时为1,结果为1,否则为0

或运算规则

0|0=0; 0|1=1; 1|0=1; 1|1=1;
即 :参加运算的两个对象,一个为1,其值为1。

异或运算规则

0^0=0; 0^1=1; 1^0=1; 1^1=0;

即:参加运算的两个对象,如果两个位为“异”(值不同),则该位结果为1,否则为0。

题意:
给了你两个数组,一个数组 b i = a i − 1 ∣ a i b_i=a_{i-1}|a_i bi=ai1ai,一个数组是 c i = a i − 1 + a i c_i=a_{i-1}+a_i ci=ai1+ai,然后让你求数组a

思路:
要知道一个重要性质!
a + b a+b a+b = = = a a a & b b b + a ∣ b +a|b +ab = = == == d i = ( a i d_i=(a_i di=(ai & a i − 1 ) = c i − b i a_i-1)=c_i-b_i ai1)=cibi
所以这个时候我们每一位分开考虑,即考虑 a 1 a_1 a1的几种可能取值即可
时间复杂度O( n ∗ l o g a n*loga nloga)

#include<iostream>
#include<cstring>
#include<algorithm>

using namespace std;

const int N=1e6;
int d[N],b[N],c[N];//数据范围在0~2的31次方,所以不会爆long long

int main()
{
    int n,ans=1;
    cin>>n;
    for(int i=2;i<=n;i++)
        scanf("%d",&b[i]);
        for(int i=2;i<=n;i++)
        {
            scanf("%d",&c[i]);
            d[i]=c[i]-b[i];
        }
    for(int i=0;i<31;i++)
//因为他最多是31位,所以开始枚举他的每一位,分开考虑
  {
      int x=1,y=1;//表示&、|的可行性
      for(int j=2;j<=n;j++)//枚举每一位的可能情况,要好好想想哦!我想了好久的!
      {
          int w1=(b[j]>>i)&1,w2=(d[j]>>i)&1;
          int tx=0,ty=0;
          if(w1==1&&w2==1)ty=y;//&=1,|=1,那么就只有都为1的时候
          if(w1==1&&w2==0)tx=y,ty=x;//&=0,|=1,那么即可为0,又可以为1
          if(w1==0&&w2==0)tx=x;//&=0,|=0,那么就只有都为0的情况
          x=tx,y=ty;
      }
      ans*=(x+y);
   }
   cout<<ans<<endl;
}

我感觉这里核心代码很巧妙哦!记住这个用法!

♡ \heartsuit E Rise of Shadows 点击查看 1678/1988 通过

在这里插入图片描述
在这里插入图片描述

1
2020
no
#include <bits/stdc++.h>
using namespace std;

int main(){
    int t;
    cin>>t;
    while(t--){
        int a;
        cin>>a;
        printf("no\n");
    }
    return 0;
}

这个就是要即是闰年又是质数的年,当然不存在拉,如果有人按死办法算,由于数据范围在1e7左右,那么就不能用素数筛,只能一一看

int is_prime(int x){
	if(x==1)return false;
	if(x==2)return true;
	for(int i =2; i*i <= x; i++){
		if(x%i==0)return false;
	}
	return true;
}

♡ \heartsuit K Yet Another Problem About Pi 点击查看 1268/9615 未通过

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
输入

2
5 5
1.5 1.5

输出

4
8

题意:
每隔w一个纬线,每隔d一个经线,你只能走最多 π \pi πm,请问你最多能都经过多少个格子?

思路:
沿着边走+2
沿着斜线走+3
显然,一开始的时候在区域的格点最优,这样子起始就是4!
数据范围很小,可以暴力枚举
a = m i n ( w , d ) a=min(w,d) a=min(w,d), b = ( w ∗ w + d ∗ d ) b=\sqrt{(w*w+d*d)} b=(ww+dd) ,求解满足ax+by<= π \pi π 2 x + 3 y 2x+3y 2x+3y的最大值

为了保证精度, π \pi π用这个 a c o s ( − 1 ) acos(-1) acos(1)来表示

方法一:暴力枚举

#include<iostream>
#include<cstring>
#include<algorithm>
#include<math.h>

using namespace std;

const double pi=acos(-1);
int main()
{
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    //这个是为让cin和cout的运行效率跟scanf和printf差不多
    int t;
    cin>>t;
    while(t--)
    {
        double w,d;
        cin>>w>>d;
        double a=min(w,d);
        double b=sqrt(w*w+d*d);
        int ans=0;
        for(int x=0;x<=100&&a*x<=pi;x++)//横着走x步
        ans=max(ans,2*x+3*(int)((pi-a*x)/b)+4);//要想下取整
        for(int y=0;y<=100&&b*y<=pi;y++)
            ans=max(ans,2*(int)((pi-b*y)/a)+3*y+4);
        cout<<ans<<endl;
    }
    return 0;
}

方法二:战略思维

这个名字哈哈哈哈,就是考虑性价比

#include<iostream>
#include<cstring>
#include<algorithm>
#include<math.h>

using namespace std;
typedef long long ll;
const double pi=acos(-1);
int main()
{
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    //这个是为让cin和cout的运行效率跟scanf和printf差不多
    int t;
    cin>>t;
    while(t--)
    {
        double w,d;
        cin>>w>>d;
        double a=min(w,d);
        double b=sqrt(w*w+d*d);
        int ans=0;
       double xa=a/2,xb=b/3;//这里是看这两个谁的性价比高,得到的结果是平均每一个格子所要的步长
       if(xa<xb)//走直线
       {
           int tans=(ll)(pi/a);
           ans+=tans*2;
           if(pi-(tans-1)*a>b)ans++;//如果去掉一条直线,可以走斜线的话,就+1
       }
       else
       {
           int tans=(long long)(pi/b);
           ans+=tans*3;
           if(pi-tans*b>a)ans+=2;//就是最后虽然走不了斜线了,如果能走直线
           else if(pi-(tans-1)*b>a)ans+=1;//如果去掉一条斜边可以走两个直线
       }
        cout<<ans<<endl;
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值