zoukankan      html  css  js  c++  java
  • 牛客练习赛44 B,C题

    链接:https://ac.nowcoder.com/acm/contest/634/B
    来源:牛客网
    
    给出n条线段,第i条线段的长度为ai,
    每次可以从第i条线段的j位置跳到第i + 1条线段的j+1位置。
    如果第i+1条线段长度不到j+1,那么就会回到第i条线段的0位置,然后继续跳。
    问从第i条线段的0位置跳到第n条线段需要跳多少次
    为了减少输入量,a数组将由以下方式得到
    
    unsigned int SA, SB, SC;
    int mod;
    unsigned int Rand(){
    SA ^= SA << 16;
    SA ^= SA >> 5;
    SA ^= SA << 1;
    unsigned int t = SA;
    SA = SB;
    SB = SC;
    SC ^= t ^ SA;
    return SC;
    }
    int main() {
    cin>>n>>mod>>SA>>SB>>SC;
    for(int i = 1;i <= n;++i) a[i] = Rand() % mod + 1;
    }
    输入描述:
    第一行两个正整数n,mod,表示一共有n条线段
    
    第二行3个数字,分别为SA,SB,SC
    输出描述:
    一行一个数字,表示从每条线段跳到n的次数之和。
    
    示例1
    输入
    5 5
    5 6 4
    输出
    13
    
    备注:
    1≤n≤2×1e7
    1≤mod≤6662333
    
         

    题意:(如上,a数组非键盘输入得到,而是调用上列已给函数得到a数组)

    思路: 如果线段之间跳跃中不存在归零的跳法,则ans=(1+2+3+.....(n-1))  =    n*(n-1) / 2,

      而真正的答案是ans=正常跳数+归零跳数。正常的跳数,已被求得,那么只需要再求出归零跳数即可。

      至于如何求归零跳数,逆向思维即可。

    AC代码:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<cmath>
    #include<queue>
    #include<stack>
    #include<algorithm>
    #define Max(a,b) ((a)>(b)?(a):(b))
    #define Min(a,b) ((a)<(b)?(a):(b))
    #define Mem0(x) memset(x,0,sizeof(x))
    #define Mem1(x) memset(x,-1,sizeof(x))
    #define MemX(x) memset(x,0x3f,sizeof(x))
    using namespace std;
    typedef long long ll;
    const int inf=0x3f3f3f;
    const double pi=acos(-1.0);
    
    ll n,a[20000010];
    unsigned int SA, SB, SC;
    int mod;
    unsigned int Rand(){
        SA ^= SA << 16;
        SA ^= SA >> 5;
        SA ^= SA << 1;
        unsigned int t = SA;
        SA = SB;
        SB = SC;
        SC ^= t ^ SA;
        return SC;
    }
    int main() {
        cin>>n>>mod>>SA>>SB>>SC;
        for(int i = 1;i <= n;++i) a[i] = Rand() % mod + 1;
        ll ans;
        if (n&1)
            ans=(n-1)/2*n;
        else
            ans=n/2*(n-1);
        ll tmp=a[n],cnt=0;
        for (int i=n-1;i>=1;i--){
            tmp--;
            tmp=min(a[i],tmp);
            if (tmp==0){
                cnt=cnt+(i-1);   //第i线段以上的线段在这里都要执行归零跳法
                tmp=a[i];
            }
                
        }
        cout<<ans+cnt<<endl;
        return 0;
    }
    
    




    链接:https://ac.nowcoder.com/acm/contest/634/C 来源:牛客网 题目描述 给出一个区间[L,R],求出[L,R]中孪生质数有多少对。 由于这是一个区间筛质数的模板题。所以小k不屑于去写。 所以出题人只好yy了另一道题。 定义k生互质数为满足y + k与y - k互质的数。 现在给出区间[L,R],你需要输出区间内k生互质数有多少对 我们说一对k生互质数在区间[L,R]内,当且仅当 y+k∈[L,R] y+k∈[L,R]且y−k∈[L,R] y−k∈[L,R] 输入描述: 一行三个数字L,R,k 输出描述: 一行一个数字表示区间[L,R]内的k生互质数的对数 示例1 输入 5 10 1 输出 2       说明       分别为(5,7),(7,9)
    示例2 输入
    287 11633 10
    输出 4532


    备注: 0≤L,R≤1e18 0≤L,R≤1e18 1≤k≤1e13








    题解:


    
    
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<cmath>
    #include<queue>
    #include<stack>
    #include<algorithm>
    #define Max(a,b) ((a)>(b)?(a):(b))
    #define Min(a,b) ((a)<(b)?(a):(b))
    #define Mem0(x) memset(x,0,sizeof(x))
    #define Mem1(x) memset(x,-1,sizeof(x))
    #define MemX(x) memset(x,0x3f,sizeof(x))
    using namespace std;
    typedef long long ll;
    const int inf=0x3f3f3f;
    const double pi=acos(-1.0);
    
    
    ll l,r,k;
    ll prime[500050];
    bool check[1000010];
    int cnt;
    void prim()
    {
        memset(check,false,sizeof(check));
        check[0]=check[1]=true;
        cnt=0;
        for (int i=2;i<500000;i++){
            if (!check[i])
                prime[cnt++]=i;
            for (int j=0;j<cnt&&i*prime[j]<1000000;j++){
                check[i*prime[j]]=true;
                if (i%prime[j]==0)
                    break;
            }
        }
    }
    ll a[1000010];
    int main()
    {
        prim();
        cin>>l>>r>>k;
        ll p=0;//质因数的个数 
        ll tmp=k<<1;
    /*    for (int i=0;;i++){
            if (tmp%prime[i]==0){
                a[p++]=prime[i];
                while (tmp%prime[i]==0){
                    tmp/=prime[i];
                }
            }
            if (tmp<=1)
                break;
        }*/
        for(int i=2;i*i<=tmp;i++){
            if(!(tmp%i)){
                a[p++]=i;
                while(!(tmp%i))
                    tmp/=i;
            }
        }
        if(tmp>1)
            a[p++]=tmp;
        
        ll sum=0;
        tmp=1<<p;//  存在p个质数,则有pow(2,p)种的组合数,
        for (int i=0;i<tmp;i++){
            ll t=1,s=0;   //t是质因数的公倍数,s则为选举的质因数的个数 
            for (int j=0;j<p;j++){
                if (i&(1<<j)){
                    s++;
                    t*=a[j];
                }
            }
             if(r/t>(l+2*k-1)/t){  //容斥  奇加偶减 
                if(s%2)sum-=r/t-(l+2*k-1)/t;
                else sum+=r/t-(l+2*k-1)/t;
            }        
        }
        cout<<sum<<endl; 
        return 0;
    }
    
    
    
     
  • 相关阅读:
    【IOS 开发】Object
    互联网开发-前沿与热门
    JS_call_APP native 与 html的交互
    扫描二维码区域限制
    二维码高亮
    charles抓包的使用教程
    Mac 在命令行中获得Root权限
    Mac下安装Wireshark,双击闪退
    iOS 解惑
    IOS_改变UITextField placeHolder颜色、字体
  • 原文地址:https://www.cnblogs.com/q1204675546/p/10744504.html
Copyright © 2011-2022 走看看