【JZOJ5317】【清华集训模拟】func(辗转相除法、找规律)
2017-08-23 22:48
288 查看
Description
Solution
这是一个可以找规律的题目,但是性质也是比较的好推。我们可以观察相邻的两项i,i+1,f(i)、f(i+1)的值分别是对应着x、y,然后f(2*i)=x,f(2*i+1)=x+y,f(2*i+2)=y。
然后我们可以发现相邻的两个每次都*2,他们的值也是较小的加上较大的。
那么我们可以倒着推回来,每次值是较大的减较小的,然后判断是左边的较小还是右边的较小,然后判断下标变化的情况。这样更相减损,如果打的好可能可以过。
但是我们知道更相减损是可以打成辗转相除的,遮掩可以在log的时间跑出来。
那么对于询问的值n,我们可以考虑枚举前面的数的值i,对于相邻的值(i,n)肯定只会出现一次。
时间复杂度O(nlogn)
Code
#include<iostream> #include<stdio.h> #include<string.h> #include<algorithm> #include<math.h> #define fo(i,a,b) for(i=a;i<=b;i++) using namespace std; typedef long long ll; const int maxn=1e6+7,mo=998244353; ll i,j,k,l,t,n,m,ans,a,b; ll an[maxn],er[maxn]; void dfs(ll x,ll y){ ll t; if(x==1&&y==1){ a=2;b=1; return; } if(x==y){a=b=-1;return;} if(x>y){ t=x/y-(x%y==0); dfs(x-t*y,y); if(a<0)return; a=(a+(er[t]-1)*b)%mo,b=er[t]*b%mo; } else{ t=y/x-(y%x==0); dfs(x,y-x*t); if(a<0)return; b=(b+(er[t]-1)*a)%mo,a=er[t]*a%mo; } } void write(int x) { if (!x) putchar('0');else { char s[10]; int i,j=0; for (;x>0;x/=10) s[j++]=x%10; for (i=j-1;i>=0;i--) putchar(s[i]+48); } putchar('\n'); } int main(){ freopen("func.in","r",stdin); freopen("func.out","w",stdout); // freopen("fan.out","w",stdout); scanf("%lld",&n); er[0]=1;fo(i,1,n)er[i]=er[i-1]*2%mo; fo(i,1,n){ a=b=0; dfs(i,n); if(b>0)an[++an[0]]=b%mo; } sort(an+1,an+1+an[0]); fo(i,1,an[0]){ write(an[i]); } }
相关文章推荐
- 【JZOJ5317】【清华集训2017模拟8.19】func
- jzoj5317 【清华集训2017模拟8.19】func (寻找性质)
- JZOJ 5485. 【清华集训2017模拟11.26】字符串
- JZOJ 5489. 【清华集训2017模拟11.28】海明距离
- JZOJ 5500. 【清华集训2017模拟12.10】营养餐
- 【JZOJ 5282】【清华集训2017模拟】等差划分数
- 【JZOJ5295】【清华集训2017模拟】Create
- JZOJ 5490. 【清华集训2017模拟11.28】图染色
- JZOJ 5484. 【清华集训2017模拟11.26】快乐树
- 【JZOJ 5284】【清华集训2017模拟】超级翻转
- JZOJ5483. 【清华集训2017模拟11.26】简单路径
- [JZOJ5495]【清华集训2017模拟12.09】MiniumCut
- 【JZOJ 5295】【清华集训2017模拟】Create
- JZOJ5484. 【清华集训2017模拟11.26】快乐树
- 【JZOJ5316】【清华集训模拟】merge(DP、括号序)
- 【JZOJ 5296】【清华集训2017模拟】Sequence
- 【JZOJ 5500】【清华集训2017模拟12.10】营养餐
- [JZOJ5485]【清华集训2017模拟11.26】字符串
- 【JZOJ 5495】【清华集训2017模拟12.09】MiniumCut(最小割树)
- [jzoj]5483. 【清华集训2017模拟11.26】简单路径