牛客练习赛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; }