2020.11.20NOIP模拟T1 简单题
题意
解析
我就是傻瓜本傻,最简单的一道题,一来看错题目,扫了一眼以为是求最后的\(A,B,C\),除了暴力之外想不到任何做法,还以为有循环之类的东西(实际上根本没有),然后就放弃了。
后面做完\(T2\)再看这道题,发现只用求\(C\),而且发现无论怎样操作,三个数的和都不变,所以很快列出了以下式子:
\(C'=\begin{equation} \left\{ \begin{array}{lr} 2C-sum,sum-C<=C & \\ 2C,sum-C>C & \end{array} \right. \end{equation}\)
然后我似乎是对那个什么循环有执念似的,非觉得可以找循环节,然而并不能证明循环节很短哦(说实话我考试想到了这个,但是没有在意这个证明,毕竟我不会证的结论海了去了),所以复杂度可能会飙很高,然后光荣地\(T\)掉。
正确的打开方式是:你仔细观察那个式子,(把条件移项移成\(2C>=sum\)会明显一点)你发现这玩意儿的本质是\(2\times C\%sum\),所以就把两种操作统一起来了,做\(k\)次操作最后的答案就是\(2^k\times C\%sum\)
►Code View
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#include<map>
using namespace std;
#define LL long long
#define N 2000005
#define INF 0x3f3f3f3f
LL rd()
{
LL x=0,f=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-1; c=getchar();}
while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+(c^48); c=getchar();}
return f*x;
}
LL MOD;
LL ksm(LL a,LL b)
{
LL res=1ll;
while(b)
{
if(b&1) res=res*a%MOD;
a=a*a%MOD;
b>>=1;
}
return res;
}
int main()
{
freopen("easy.in","r",stdin);
freopen("easy.out","w",stdout);
int T=rd();
while(T--)
{
LL a=rd(),b=rd(),c=rd(),k=rd();
MOD=a+b+c;
LL ans=ksm(2,k)*c%MOD;
printf("%lld\n",ans);
}
return 0;
}
/*#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#include<map>
using namespace std;
#define LL long long
#define N 2000005
#define INF 0x3f3f3f3f
LL rd()
{
LL x=0,f=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-1; c=getchar();}
while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+(c^48); c=getchar();}
return f*x;
}
map<LL,int> vis;//上一次出现的位置
LL ans[N];
int main()
{
freopen("easy.in","r",stdin);
freopen("easy.out","w",stdout);
int T=rd();
while(T--)
{
LL a=rd(),b=rd(),c=rd(),k=rd(),len;
LL sum=a+b+c;
vis.clear();
vis[c]=0;
ans[0]=c;
int pos=0;
while(1)
{
if(sum-c<=c) c=2*c-sum;
else c=2*c;
if(vis[c])
{
len=pos-vis[c]+1;
break;
}
vis[c]=++pos;
ans[pos]=c;
}
if(k<=vis[c]-1)
{
printf("%lld\n",ans[k]);
continue;
}
k-=(vis[c]-1);
int r=k%len;
if(r==0) r=len;
printf("%lld\n",ans[vis[c]+r-1]);
}
return 0;
}*/
转载请注明出处,有疑问欢迎探讨
博主邮箱 2775182058@qq.com