题目链接:http://bestcoder.hdu.edu.cn/contests/contest_show.php?cid=690
Problem A
思路:先预处理开始位置到每一个位置的结果。假设要求区间为[a,b],开始位置到位置i的结果为f(i),那么区间[a,b]所求结果为f(b)/f(a-1),但是不一定能整除,所以需要处理一下。因为模为p=9973,是一个素数。根据费马小定理,假设p是一个素数,且(a,p)=1,那么a^(p-1)≡1 (mod p)。即:假如a是整数,p是素数,且a,p互质(即两者只有一个公约数1),那么a的(p-1)次方除以p的余数恒等于1。所以,假设x≡f(b)/f(a-1) (mod p)(这里的p即为题中的模),又有(f(a-1))^(p-1) ≡ 1 (mod p),根据同余性质,有x≡f(b)*(f(a-1))^(p-2) (mod p),此即为答案。
附上AC代码:
#include <iostream>
#include <algorithm>
using namespace std;
const int mod = 9973;
const int maxn = 100005;
int h[maxn];
int n;
string str;
int quick_pow(int a, int b){
int ans = 1;
while (b){
if (b & 1)
ans = ((ans%mod)*(a%mod))%mod;
a = ((a%mod)*(a%mod))%mod;
b >>= 1;
}
return ans;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
while (cin >> n){
cin >> str;
h[0] = 1;
for (int i=1; i<=str.size(); ++i)
h[i] = (h[i-1]*(str[i-1]-28))%mod;
int a, b;
while (n--){
cin >> a >> b;
if (a > b)
swap(a, b);
int t = quick_pow(h[a-1], mod-2);
int ans = (h[b]*t)%mod;
cout << ans << endl;
}
}
return 0;
}
Problem B
思路:明显的斐波拉契数列,因为n很大,所以用Java实现。
附上AC代码:
import java.util.Scanner;
import java.math.BigInteger;
import java.util.Arrays;
import java.math.BigDecimal;
public class Main{
final static int MAXN = 205;
public static void main(String args[]){
Scanner in = new Scanner(System.in);
BigInteger fac[] = new BigInteger[MAXN];
fac[0] = fac[1] = BigInteger.ONE;
for (int i=2; i<MAXN; ++i)
fac[i] = fac[i-1].add(fac[i-2]);
while (in.hasNext()){
int n = in.nextInt();
System.out.println(fac[n]);
}
in.close();
}
}
Problem D
思路:因为数据不是太大,所以直接map搞定。直接上代码吧!
附上AC代码:
#include <iostream>
#include <string>
#include <map>
#include <algorithm>
using namespace std;
map<string, int> cnt;
int n;
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cin >> n;
string str;
while (n--){
cin >> str;
sort(str.begin(), str.end());
cout << cnt[str] << endl;
++cnt[str];
}
return 0;
}