B Counting Inversion
题解:数位dp,参考。对于g的定义,描述为第i+1位取值为j时 与 第1到i位 产生的逆序数之和更合适一些(大概)。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MOD = 1e7+7;
const int maxn = 1e6+10;
int n;
ll x, y;
int cnt = 0;
int num[20];
ll vis[20][2][2], f[20][2][2], g[20][2][2][20], G[20][2][2];//当前位数、是否有限制、前导零 数字i
//vis用来标记状态是否出现
//f为当前状态向后转移所能到达的状态总数
//g为当前状态向后走能到达的状态中(包括u相同的状态) 比当前位置i大的数字出现的次数
//G为当前状态时的逆序数之和
void dfs(int u, int lim, int ze){
if(vis[u][lim][ze]==cnt) return ;
vis[u][lim][ze] = cnt;
f[u][lim][ze] = 0;
G[u][lim][ze] = 0;
for(int i = 0; i <= 9; i++)
g[u][lim][ze][i] = 0;
if(u==0){//递归边界
f[u][lim][ze] = 1;
return ;
}
//枚举当前位置
for(int i = 0; i <= (lim?num[u]:9); i++){
int lim2 = (lim&&i==num[u]), ze2 = (ze&&i==0);
dfs(u-1, lim2, ze2);
f[u][lim][ze] += f[u-1][lim2][ze2];//后续位置产生的状态数
if(!(ze&&i==0)){
for(int j = 0; j <= i; j++)
g[u][lim][ze][j] += f[u-1][lim2][ze2];
G[u][lim][ze] += g[u-1][lim2][ze2][i+1];
}
for(int j = 0; j <= 9; j++)
g[u][lim][ze][j] += g[u-1][lim2][ze2][j];
G[u][lim][ze] += G[u-1][lim2][ze2];
}
}
ll solve (ll x){
++cnt;
int len = 0;
while(x){
num[++len] = x%10;
x/=10;
}
dfs(len, 1, 1);
return G[len][1][1];
}
int main(){
ios::sync_with_stdio(false);
cin >> n;
for(int i = 0; i < n; i++){
cin >> x >> y;
solve(y);
printf("Case %d: %lld\n", i+1, solve(y)-solve(x-1));
}
// system("pause");
return 0;
}
C:Divisors of the Divisors of An Integer
收获:唯一分解定理
题解:
唯一分解定理:X=P1a1 P2a2 ……Pnan , 其中P为质因子,有X的因子个数为
(
a
1
+
1
)
∗
(
a
2
+
1
)
∗
(
a
3
+
1
)
…
…
(
a
n
+
1
)
(a_1+1)*(a_2+1)*(a_3+1)……(a_n+1)
(a1+1)∗(a2+1)∗(a3+1)……(an+1)
不妨设N!=P1a1 P2a2 ……Pnan,对于N!的一个因子f,有 f = P1c1 P2c2 ……Pncn (0≤ci≤ai)。则f的因子个数为
(
c
1
+
1
)
∗
(
c
2
+
1
)
…
…
(
c
n
+
1
)
(c_1+1)*(c_2+1)……(c_n+1)
(c1+1)∗(c2+1)……(cn+1),所以总因子个数等于
∏
i
=
1
n
(
c
i
+
1
)
\prod_{i=1}^n(c_i+1)
∏i=1n(ci+1),其中
c
i
有
a
i
+
1
种
取
值
c_i有a_i+1种取值
ci有ai+1种取值。若将其余项看做定值t,则式子就变成
t
∗
∑
c
i
=
0
c
i
=
a
i
c
i
+
1
t*\sum_{c_i=0}^{c_i=a_i}c_i+1
t∗∑ci=0ci=aici+1,也就是
t
∗
(
a
i
+
1
)
∗
(
a
i
+
2
)
2
t*\frac{(a~i~+1)*(a~i~+2)}{2}
t∗2(a i +1)∗(a i +2),其余项同理得总个数为
∏
i
=
1
n
(
a
i
+
1
)
∗
(
a
i
+
2
)
2
\prod_{i=1}^n\frac{(a~i~+1)*(a~i~+2)}{2}
∏i=1n2(a i +1)∗(a i +2),问题就变成求N!有多少个质因子。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MOD = 1e7+7;
const int maxn = 1e6 + 10;
ll prime[maxn], vis[maxn];
ll cnt = 0, n;
void getPrime(){
memset(vis, 1, sizeof(vis));
vis[0] = vis[1] = 0;
for(ll i = 2; i < maxn; i++){
if(vis[i]){
prime[cnt++] = i;
for(ll j = i*2; j < maxn; j+=i)
vis[j] = 0;
}
}
}
int main(){
getPrime();
while(scanf("%d",&n)&&n){
ll ans = 1;
for(ll i = 0; prime[i]<=n; i++){
ll tmp = n, c = 0;
while(tmp){//求含有因子prime[i]的个数 与100!中有多少个0的求法相同
c+=tmp/prime[i];
tmp/=prime[i];
}
ans = ( ans*(c+2) * (c+1)/2)%MOD;
}
printf("%lld\n",ans);
}
//system("pause");
return 0;
}
E Helping the HR
题解:模拟题,仔细阅读,理解题意即可做出。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MOD = 1e7+7;
const int maxn = 1e6+10;
int n, ans;
int prime[maxn], vis[maxn];
int cnt = 0;
int main(){
int dstay=8*60*60, estay=9*60*60;
int arr_st=8*60*60+30*60, darr_ed=9*60*60+30*60, earr_ed=12*60*60+30*60;
ios::sync_with_stdio(false);
while(scanf("%d",&n)==1&&n){
char ch; int ha, ma, sa, hb, mb, sb;
int cnt = 0;
getchar();
for(int i = 0; i < n; i++){
scanf("%c:%d:%d:%d:%d:%d:%d",&ch, &ha, &ma,&sa, &hb, &mb, &sb);getchar();
// cout<<ch<<endl;
int ta = ha*60*60+ma*60+sa, tb=hb*60*60+mb*60+sb;
ta = max(arr_st, ta);//不得早于8:30
int len = tb-ta;//时长
if(ch=='D'){
//判断迟到
if(ta>darr_ed) cnt++;
//判断时长
else if(len<dstay) cnt++;
}
else if(ch=='E'){
if(ta>earr_ed) cnt++;
else if(len<estay) cnt++;
}
}
//根据cnt 分为0,1&2,3
if(cnt==0) cout << "All OK" << endl;
else if(cnt>3) cout << "Issue Show Cause Letter" << endl;
else cout << cnt << " Point(s) Deducted" << endl;
}
// system("pause");
return 0;
}
H Tile Game
题解: 输入为一个稳定态,求从该状态出发能够到达多少个不同的稳定态
上下左右的移动操作是可逆的,所以只需要按固定的顺序操作即可,例如顺时针操作,上右下左。显然不同稳定态的形状不一样,只是骨牌的摆放不同,而每一个骨牌在这些状态中的位置 呈循环变化;----条件1
并且对于一个位置来说,来过该位置的骨牌是固定,也呈循环变化—条件2
易证两个循环的周期是一样的,记录循环的长度,并且区分不同状态的标志就是骨牌的位置,所以长度还代表了不同状态的数量,易证周期的最小公倍数即为答案。
关于周期的计算 从初始状态1开始 模拟一次"上右下左"操作 到达状态2周期变为1,再根据条件2可以算出周期的长度
#include<bits/stdc++.h>
using namespace std;
#define pii pair<int, int>
typedef long long ll;
const int maxn = 200*200 + 10;
const ll MOD = 78294349ll;
int t, r, c;//
int st[205][205], ed[205][205];//分别记录初始稳定态骨牌的位置,以及另一稳定态骨牌的位置
int prime[maxn], vis[maxn];
pii poi[maxn];
int get_prime(){
int cnt = 0;
memset(vis, 1, sizeof(vis));
vis[0] = vis[1] = 0;
for(int i = 2; i < maxn; i++){
if(vis[i]){
prime[cnt++] = i;
for(int j = 2*i; j < maxn; j+=i){
vis[j] = 0;
}
}
}
return cnt;
}
void move_up(){
int cnt;
for(int j = 0; j < c; j++){
cnt = 0;
for(int i = 0; i < r; i++){
if(ed[i][j]==0) cnt++;
else{
ed[i-cnt][j] = ed[i][j];
if(cnt) ed[i][j] = 0;
}
}
}
}
void move_right(){
int cnt;
for(int i = 0; i < r; i++){
cnt = 0;
for(int j = c-1; j >= 0; j--){
if(ed[i][j]==0) cnt++;
else{
ed[i][j+cnt] = ed[i][j];
if(cnt) ed[i][j] = 0;
}
}
}
}
void move_down(){
int cnt;
for(int j = 0; j < c; j++){
cnt = 0;
for(int i = r-1; i >= 0; i--){
if(ed[i][j]==0) cnt++;
else{
ed[i+cnt][j] = ed[i][j];
if(cnt) ed[i][j] = 0;
}
}
}
}
void move_left(){
int cnt;
for(int i = 0; i < r; i++){
cnt = 0;
for(int j = 0; j < c; j++){
if(ed[i][j]==0) cnt++;
else{
ed[i][j-cnt] = ed[i][j];
if(cnt) ed[i][j] = 0;
}
}
}
}
int main(){
ios::sync_with_stdio("pause");
int len = get_prime();
cin >> t;
for(int k = 0; k < t; k++){
memset(vis, 0, sizeof(vis));
int cnt = 0;
cin >> r >> c;
string s;
for(int i = 0; i < r; i++){
cin >> s;
for(int j = 0; j < c; j++){
if(s[j]=='.') st[i][j] = 0;
else {
st[i][j] = ++cnt;
poi[st[i][j]] = make_pair(i, j);
}
ed[i][j] = st[i][j];
}
}
//模拟一次“上右下左”
move_up();
move_right();
move_down();
move_left();
//根据条件2 计算每一个骨牌位置变化的周期
for(int i = 1; i <= cnt; i++){
int num = 1;//周期
pii curp = poi[i];
int curi = ed[curp.first][curp.second];
while(i!=curi){
num++;
curp = poi[curi];
curi = ed[curp.first][curp.second];
}
for(int j = 0; num>1 && j < len; j++){
int cnt = 0;
while(num%prime[j]==0){
cnt++;
num /= prime[j];
}
vis[j] = max(cnt, vis[j]);
}
}
//计算周期的最小公倍数
ll ans = 1;
for(int i = 0; i < len; i++)
while(vis[i]-->0)
ans = ans * prime[i] % MOD;
cout << "Case " << k+1 << ": " << ans << endl;
}
// system("pause");
return 0;
}
F Path Intersection
题解:树上路径交,emmmmm,之后再补
J VAT Man
题解:签到题
#include<bits/stdc++.h>
using namespace std;
int main(){
int t;
cin >> t;
double price;
while(t--){
cin >> price;
double output = price * 1.15;
cout << fixed << setprecision(2)
<< output << endl;
}
// system("pause");
return 0;
}