http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=2715
题目意思很简单就是输入2个数n,k叫你求sigma(f(i))%k (1<=i<=n)
我的算法很明显不是最好的,跑了780MS+,不过在取mod时候稍微优化下应该是几百MS的级别吧...不说了下面说下思路
利用2的特点
扫描出现2,那么马上可以使循环变量直接跳:
如:
扫描到2000(3)的时候,那么直接下次就计算10000,因为2000~2222的结果完全一样
扫描到112000(3)的时候,那么下次就计算120000(3),因为112000~112222的结果仍然是一样,这样优化下就可以过了
比赛的时候偶是第一个AC的hihi~
- #include<iostream>
- using namespace std;
- int cnt,tot;
- int tmp[50];
- int pri(int n)
- {
- int l=0,tn=n,i,tp=0;
- while(n)
- {
- tmp[l++]=n%3;
- n/=3;
- }
- for(i=l-1;i>=0;i--)if(tmp[i]==2)break;else tp=tp*3+tmp[i];
- cnt=i;
- tot=l-1;
- if(i==-1)return tn;
- if(i==l-1)return 0;
- return tp;
- }
- int ppow(int a,int b)
- {
- int ret=1;
- for(;b;b>>=1,a*=a)if(b&0x1)ret*=a;
- return ret;
- }
- int main()
- {
- int i,n,ans,tm,c,k;
- while(scanf("%d%d",&n,&k)!=EOF)
- {
- ans=0;
- for(i=1;i<=n;i++)
- {
- tm=pri(i);
- if(cnt==-1)
- ans+=tm;
- else if(!tm)
- i=ppow(3,tot+1)-1;
- else
- {
- if(i+(c=ppow(3,cnt))>n)
- ans+=((n-i+1)%k)*(tm%k);
- else ans+=(c%k)*(tm%k);
- i+=c-1;
- }
- ans%=k;
- }
- printf("%d/n",ans);
- }
- return 0;
- }