把博客园图标替换成自己的图标
把博客园图标替换成自己的图标end

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;
}*/
posted @ 2020-11-20 22:13  Starlight_Glimmer  阅读(192)  评论(0编辑  收藏  举报
浏览器标题切换
浏览器标题切换end