A題:Flipping Game
題意:n個數字由0,1組成,一次反轉定義爲將連續的n個0翻轉爲1.求經過一次翻轉後,1的個數做多是多少???
很水的一道題,方法就是求出1的個數和連續0個數最多的區間長度。二者相加就是答案~~~
#include <iostream>
#include<stdio.h>
using namespace std;
int main()
{
int i,n,a,x,y,mx;
cin >> n;
mx=0,x=0,y=0;
for(i=0;i<n;i++)
{
cin >> a;
if(a) y++;
if(!a)
{
x++;
if(x>mx)
mx=x;
}
else if(x>0) x--;
}
if(!mx) mx--;
cout << y + mx << endl;
return 0;
}
B題:Hungry Sequence
這道題,要求不是很嚴格~~只要輸出那個數,其中任意兩個數不能整除就可以,那麼n—2*n-1之間的連續n個數任意兩個都不能整除,輸出即可
#include <iostream>
using namespace std;
int main()
{
int n,i;
cin>>n;
for(i=n; i<2*n; ++i)
cout << i << " ";
return 0;
}
C題:Magic Five
題意:有一個字符串,可以在這個串中去掉0個或者多個(不能全部)字符使能夠被5整除。求共有多少種方式?
輸入:一個字符串s和整數k,表示k個s相連接。
輸出:有多少種方式是字符串表示的數能夠被5整除。
解題方法:根據快速冪和費馬小定理求解。否則會TLE。
思路:設max=1000000007先求出一個字符串的長度l,在求出一個串時的方法數a1,那麼家下來k-1接上的時候會成一個等比數列,即:a1,a1*( 2 ^ l ),a1*( 2 ^ (2l) ),…………,
a1*( 2 ^ (k-1)l )。那麼如果根據等比數列前n項和的公式求出:sum=a1 * ( 2 ^ ( k* l) -1 )/( 2 ^ l -1 )。這樣做的話會wa掉,因爲有除法,分子要對max取模,那麼就不一定能夠整除分母。下面採用費馬小定理求逆元的辦法。
設分子爲a,分母爲b。那麼sum=a1* a/b%max。設b的逆元是p,那麼b*p=1。那麼,sum=a1*a*p%max。那接下來胖怎麼求呢?
根據費馬小定理:a ^ (p-1)=1(mod p),前提是a,p互質。有題知:b和max互質,則b ^ (max-1)=1(mod max)。所以b*b^(max-2)=1;即p=b^(max-2)。
所以,sum=((a1*a)%max)*(b ^ (max-2))%max,其中a=2 ^ ( k* l) -1,b=2 ^ l -1。式子中所有的冪數都要用快速冪來求。
這道題,受益良多啊~~~快速冪更加深了印象,還學會了費馬小定理~~~。
code:
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <string>
#include <cmath>
using namespace std;
#define MAX 1000000007
__int64 mode(__int64 a, __int64 n)
{
__int64 t = a;
__int64 ans = 1;
while(n)
{
if(n & 1)
{
ans = ans * t%MAX;
}
n >>= 1;
t = t * t%MAX;
}
return ans;
}
int main()
{
__int64 k,t1,t2;
string s;
cin >> s >> k;
__int64 i,ans=0,sum=1;
__int64 l1=s.length();
for(i=l1-1; i>=0; i--)
{
if(s[i]=='0'||s[i]=='5')
ans=(ans+mode(2,i))%MAX;
}
ans=((ans*(mode(2,l1*k)-1))%MAX)*mode(mode(2,l1)-1,MAX-2)%MAX;
cout << ans%MAX << endl;
return 0;
}
D題:Block Tower
題意:
.代表空地,#代表洞,空地可以建塔。塔分爲兩種:藍色的塔,可以建在空地上。紅色的塔,必須周圍有藍色的纔可以建。還可以將藍色的拆掉在建紅色的。求建成紅色塔最多的過程~~~,注意Note, that you shouldn't minimize the number of operations這句話,說明答案不是唯一的~~~
思路:dfs搜素就可以了,
code:
#include <iostream>
#include <stdio.h>
#include <string>
#include <algorithm>
using namespace std;
char map[550][550];
int vis[550][550]={{0}};
char c[100000005];
int x[100000005];
int y[100000005];
int m,n;
int sum=0;
void dfs(int a,int b,int t)
{
if(a<1||a>n||b<1||b>m)return ;
c[sum]='B';
x[sum]=a;
y[sum]=b;
sum++;
vis[a][b]=0;
if(vis[a-1][b])
dfs(a-1,b,1);
if(vis[a+1][b])
dfs(a+1,b,1);
if(vis[a][b-1])
dfs(a,b-1,1);
if(vis[a][b+1])
dfs(a,b+1,1);
if(t)
{
c[sum]='D';
x[sum]=a;
y[sum]=b;
sum++;
c[sum]='R';
x[sum]=a;
y[sum]=b;
sum++;
}
}
int main()
{
int i,j;
cin >> n >> m;
for(i=1; i<=n; i++)
for(j=1; j<=m; j++)
{
cin >> map[i][j];
if(map[i][j]=='.')
vis[i][j]=1;
}
for(i=1; i<=n; i++)
for(j=1; j<=m; j++)
{
if(vis[i][j])
dfs(i,j,0);
}
cout << sum << endl;
for(i=0; i<sum; i++)
{
cout << c[i] << " " << x[i] << " " << y[i] << endl;
}
return 0;
}
E題:Axis Walking
題意:有n個數,那麼由這n個數到達這些數的總和,但是不能到達給出的指定的數。求出共有多少種方式到達?
思路:狀態壓縮DP,還沒有懂,先轉過來~~~~
01.#include <iostream>
02.#include <cstdio>
03.#include <algorithm>
04.#include <string>
05.#include <cmath>
06.#include <cstring>
07.#include <queue>
08.#include <set>
09.#include <vector>
10.#include <stack>
11.#include <map>
12.#include <iomanip>
13.#define PI acos(-1.0)
14.#define Max 2505
15.#define inf 1<<28
16.#define LL(x) ( x << 1 )
17.#define RR(x) ( x << 1 | 1 )
18.#define REP(i,s,t) for( int i = ( s ) ; i <= ( t ) ; ++ i )
19.#define ll long long
20.#define mem(a,b) memset(a,b,sizeof(a))
21.#define mp(a,b) make_pair(a,b)
22.#define PII pair<int,int>
23.using namespace std;
24.
25.#define MOD 1000000007
26.
27.inline void RD(int &ret) {
28. char c;
29. do {
30. c = getchar();
31. } while(c < '0' || c > '9') ;
32. ret = c - '0';
33. while((c=getchar()) >= '0' && c <= '9')
34. ret = ret * 10 + ( c - '0' );
35.}
36.
37.int a[111111] ;
38.int sum[1 << 24] ;
39.int dp[1 << 24] ;
40.int k[11] ;
41.
42.int main(){
43.
44. int n ;
45. cin >> n ;
46. for (int i = 0 ;i < n ; i ++ ){
47. RD(a[i]) ;
48. }
49.
50. int m ;
51. cin >> m ;
52. for (int i = 0 ;i < m ;i ++ ){
53. RD(k[i]) ;
54. }
55. dp[0] = 1 ;
56. for (int i = 1 ;i < (1 << n) ; ++ i){//枚舉當前路徑
57. int pos ;
58. bool flag = 0 ;
59. sum[i] = 0 ;
60. for (int j = 0 ;j < n ;j ++ ){
61. if(i & (1 << j)){//i 在 j 這點爲1 ,直接在這裏找出sum[i]的值會T。O(2 ^ 24 * n)
62. pos = j ;//一開始我直接寫sum[i] += a[j] ;就T了
63. break ;
64. }
65. }
66. sum[i] = sum[i ^ (1 << pos)] + a[pos] ;//i 狀態的所有步數。
67. for (int j = 0 ; j < m ;j ++ ){//i狀態的步數是否不能走。
68. if(sum[i] == k[j]){
69. dp[i] = 0 ;
70. flag = 1 ;
71. break ;
72. }
73. }
74. if(flag)continue ;
75. dp[i] = 0 ;
76. for (int j = 0 ;j < n ;j ++ ){
77. if(i & (1 << j)){//i 這位可以由i ^ (1 << j )這一狀態過來。
78. dp[i] = (dp[i] + dp[i ^ (1 << j)]) ;
79. if(dp[i] >= MOD)dp[i] -= MOD ;
80. }
81. }
82. }
83.
84. cout << dp[(1 << n) - 1] << endl;
85. return 0 ;
86.}