["扫地"杯III day2]染色问题

描述 Description
做了HEOI2012的赵州桥(bridge)之后,liouzhou_101就感到极其的不爽,首先那题题目叙述巨渣,然后做法极坑。
不过那题是一道和染色有关的问题,于是在此同时也启发liouzhou_101想到了这样一个简单的问题:
在一串未打结的项链上(意思就是说项链的左端和右端不相连),有N颗珠子,你有M种颜色,然后就问你有多少种方法将每一颗珠子都染上颜色,使得任意两颗相邻的珠子的颜色不同。
liouzhou_101这种傻×自然不会做了,于是来向你请教…
当然,由于liouzhou_101的脑子构造极其简单,你不要想太多,请不要考虑Polya之类的本质相同,否则的话仅凭liouzhou_101的理解能力是不能理解的
输入格式 InputFormat
输入只有一行,三个正整数N、M和P,之间以一个空格隔开。

 
输出格式 OutputFormat
输出只有一行,表示染色的方法总数模P。
 
 
 
数据范围和注释 Hint
一共有324种染色方法,对13取模后是12。

对于10%的数据,N=1,M<=10,P<=10;
对于20%的数据,N<=10,M<=10,P<=100;
对于50%的数据,N,M,P<=1,000,000,000;
对于100%的数据,1<=N,M,P<=1,000,000,000,000,000,000,且M>=2。
 
 
 
 
 
看了题解第二种巧妙的解法后,我竟然还是傻帽的二分求2^xmodP的值,傻傻……
 1 #include<iostream>
 2 #include<cmath>
 3 #include<cstdio>
 4 #include<fstream>
 5 using namespace std;
 6 //ifstream fin("cin.in");
 7 //ofstream fout("test.out");
 8 
 9 long long N,M,P;
10 
11 long long s,t;int totx=1,toty=1;long long f[140];
12 long long Yu(long long x,long long y){
13      long long ans=0;s=x;totx=0;
14      while(s>0)
15      {
16        if(s&1)
17        {
18          t=y;toty=0;
19          while(t>0)
20          {
21            if(t&1) 
22            {ans+=f[totx+toty];ans%=P;}
23            t>>=1;toty++;
24                    }
25               } 
26        s>>=1;totx++;
27                     }
28      return ans;
29      }
30 
31 long long FangM(long long n){
32      if(n==0) return 1;
33      if(n==1) return M%P;
34 
35      long long ans=FangM(n/2);
36      ans=Yu(ans,ans);
37      if(n&1) ans=Yu(ans,M);
38      return ans;
39      }
40 
41 int main()
42 {
43     cin>>N>>M>>P;
44     N--;M--;
45     f[0]=1;
46     for(int i=1;i<140;++i)
47     f[i]=(2*f[i-1])%P;
48     long long ans=FangM(N);
49     ans=Yu(ans,M+1);
50     cout<<ans<<endl;
51     return 0; 
52     
53     }

 

posted on 2012-11-03 11:26  怡红公子  阅读(322)  评论(0编辑  收藏  举报