牛客练习赛44 B题 (思维)
作者:互联网
链接: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; }
标签:tmp,练习赛,int,44,跳数,牛客,SA,include,线段 来源: https://www.cnblogs.com/q1204675546/p/10744504.html