A.Wasserstein Distance

（水题）

#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<algorithm>
using namespace std;
#define inf 0x3f3f3f3f
#define ll long long
const int maxn = 1e5 + 500;
ll a[maxn], b[maxn];
int main()
{
int t;
cin >> t;
while (t--)
{
int n;
cin >> n;
for (int i = 0; i < n; i++)
scanf("%lld", &a[i]);
for (int i = 0; i < n; i++)
scanf("%lld", &b[i]);
ll h = 0, ans = 0;
for (int i = 0; i < n - 1; i++)
{
a[i] += h;
h = a[i] - b[i];
ans += abs(h);
}
cout << ans << endl;
}
return 0;
}

B.合约数

（树+dfs+素数筛）

#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<algorithm>
using namespace std;
#define inf 0x3f3f3f3f
#define ll long long
#define mod (ll)(1e9+7)
const int maxn = 2e4 + 500;
vector<int>h[maxn];//合约数
bool impri[maxn];//合数
vector<int>tre[maxn];
ll cnt[maxn];
ll a[maxn];
ll ans;
void fun() {//先打表得出1e4内所有数的合约数
for (int i = 2; i <= (int)1e4; i++) { //素数塞
if (!impri[i]) {
for (int j = i + i; j <= (int)1e4; j += i)
impri[j] = true;
}
}
for (int i = 4; i <= (int)1e4; i++) {//打表得到合约数
if (!impri[i])continue;//素数
for (int j = i; j <=(int)1e4; j+=i)
h[j].push_back(i);//约数
}
}
void dfs(int v, int pre)
{
//先预处理当前结点所有合约数出现时当前节点对ans的贡献
for (int i = 0; i < h[a[v]].size(); i++)
cnt[h[a[v]][i]] = (cnt[h[a[v]][i]] + v) % mod;

//在当前结点对之前的祖先结点预处理的贡献值取出加到ans上
ans = (ans + cnt[a[v]]) % mod;

for (int i = 0; i < tre[v].size(); i++)
{
if (tre[v][i] == pre)continue;
dfs(tre[v][i], v);
}

//回溯前需要减去当前结点对后代子孙结点的贡献，因为回溯回父结点不属于其子孙
for (int i = 0; i < h[a[v]].size(); i++)
cnt[h[a[v]][i]] = (cnt[h[a[v]][i]] + mod - v) % mod;
}
int main()
{
fun();
int t;
cin >> t;
while (t--)
{
int n, p, u, v;
scanf("%d%d", &n, &p);
for (int i = 1; i <= n; i++)
tre[i].clear();
for (int i = 0; i < n - 1; i++)
{
scanf("%d%d", &u, &v);
tre[u].push_back(v);//不能只存单向边，因为我们不清楚哪个是父结点
tre[v].push_back(u);//遍历的时候跳过父结点即可
}
for (int i = 1; i <= n; i++)
scanf("%lld", &a[i]);
ans = 0;
dfs(p, -1);
printf("%lld\n", ans);
}
return 0;
}

C.序列变换

（贪心+STL）

#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<algorithm>
using namespace std;
#define inf 0x3f3f3f3f
#define ll long long
const int maxn = 1e4 + 500;
int a[10], b[10], tmp[10];
int cost[10][10];
int n;
//获取a[]数组变换前后的最小调换次数（魔法一）
int fun2()
{
int ret = 0;
int t[10];
for (int i = 0; i < n; i++)
t[i] = tmp[i];
for (int i = 0; i < n; i++)
{
if (t[i] == i)continue;
for (int j = i + 1; j < n; j++)
{
if (t[j] == i)
{
t[j] = t[i]; ret++; break;
}
}
}
return ret;
}
//获取当前tmp[]（对a[]数组使用魔法一后的数组）中每个tmp[i]变为b[i]的最少次数(魔法二，三）
int fun1(int i, int j)//可先预处理出来存入cost[i][j]中
{
int x = a[i], y = b[j];
if (x > y)swap(x, y);
int ret = 0;
while (1)
{
if (y % 2 == 1)
{
ret++; y--;
}
if (y >> 1 >= x)
{
y >>= 1; ret++;
}
else break;
}
return ret + y - x;
}
int solve()
{
int ret = fun2();
for (int i = 0; i < n; i++)
ret += cost[i][tmp[i]];
return ret;
}
int main()
{
int t;
scanf("%d", &t);
while (t--)
{
scanf("%d", &n);
for (int i = 0; i < n; i++)
{
scanf("%d", &a[i]);
tmp[i] = i;
}
for (int i = 0; i < n; i++)
scanf("%d", &b[i]);
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
cost[i][j] = fun1(i, j);
int ans = solve();
while (next_permutation(tmp, tmp + n))
ans = min(ans, solve());
printf("%d\n", ans);
}
return 0;
}

D.数字游戏

E.小Y吃苹果

（水题）

#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<algorithm>
using namespace std;
#define inf 0x3f3f3f3f
#define ll long long
int main()
{
int n;
cin >> n;
int x = 1;
for (int i = 0; i < n; i++)
x *= 2;
cout << x << endl;
return 0;
}

F.1 + 2 = 3 ?

（找规律=》二进制斐波那契）

#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<algorithm>
using namespace std;
#define inf 0x3f3f3f3f
#define ll long long
const int maxn = 1e4 + 500;
ll f[maxn],a[maxn];//1000000000000
void fun()
{
f[1] = 1; f[2] = 1;
a[1] = 1, a[2] = 2;
for (int i = 3;; i++)
{
f[i] = f[i - 1] + f[i - 2];
a[i] = a[i - 1] + f[i];
if (a[i] > (ll)1e12)  break;

}
}
int main()
{
fun();
int t;
cin >> t;
while (t--)
{
ll n;
scanf("%lld", &n);
int x[60]={0};
while (n)
{
int p = lower_bound(a, a + 59, n) - a;
n -= (a[p - 1] + 1);
x[p] = 1;
}
ll ans = 0,k=1;
for (int i = 1; i < 60; i++)
{
if (x[i] == 1)
ans += k;
k <<= 1;
}
cout << ans << endl;
}
return 0;
}

G.小Y做比赛

（贪心+双指针模拟2个优先队列）

第一步： x[]数组保存a的时间，xy[]数组保存a+b的时间，对他们都进行升序排序取（并且要记录下标）

第二步：取最小读题时间的x[q=0]数组第一个数对应的题号（默认先读他了）然后用一个b0保存他的b

第三步：j接下来还需要ac多n-1个题，取题通过比较xy[p].v的值即a2+b2 和x[q].v+b0的值a2+b1

(这里1指前一题，2指后一题，若是后者小b0也需要变为b2）

最后把b0也加上就得到最后一题的ac时间。（代码中t是时间轴，因此每次ac题目ans+=t】

#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<algorithm>
using namespace std;
#define inf 0x3f3f3f3f3f3f
#define ll long long
const int maxn = 1e5 + 500;
struct node
{
ll v;
int index;
}xy[maxn],x[maxn];
ll b[maxn];
bool vis[maxn];
bool cmp(node xx, node yy)
{
return xx.v < yy.v;
}
int main()
{
int n;
cin >> n;
for (int i = 0; i < n; i++)
{
scanf("%lld%lld", &x[i].v, &b[i]);
xy[i].v = x[i].v + b[i];
xy[i].index = i; x[i].index = i;
}
sort(xy, xy + n,cmp);
sort(x, x + n,cmp);
int p = 0, q = 0;//2个指针分别是记录xy[],x[]遍历到的位置
ll t = x[q].v, b0 = b[x[q].index]; vis[x[q++].index] = true; //取第一组数据
int cnt = 1;
ll ans = 0;
while (cnt++!= n)
{
while (vis[xy[p].index]) p++;
while (vis[x[q].index]) q++;
if (xy[p].v <= x[q].v + b0)
{
vis[xy[p].index] = true;
t += xy[p++].v;
ans += t;
}
else
{
vis[x[q].index] = true;
t += x[q].v + b0;
b0 = b[x[q++].index];
ans += t;
}
}
t += b0;
ans += t;
cout << ans << endl;
return 0;
}

H.小Y与多米诺骨牌

I.二数

（找规律）

【eg:与2544差值最小的二数是2600和2488（取2488），25443时取24888，25445时取26000】

#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<algorithm>
using namespace std;
#define inf 0x3f3f3f3f
#define ll long long
const int maxn = 1e5 + 500;
char s[maxn];
int main()
{
int t;
scanf("%d", &t);
while (t--)
{
scanf("%s", &s);
int pos = -1, len = strlen(s);
for (int i = 0; i < len; i++)
{
if ((s[i] - '0') % 2 != 0)
{
pos = i; break;
}
}
if (pos != -1)//存在奇数，需要修改，变大或变小
{
if (s[pos] == '9')
for (int i = pos; i < len; i++)
s[i] = '8';
else
{
int k = 1;
for (int i = pos + 1; i < len; i++)
{
if (s[i] < '4')
{
k = 2; break;
}
else if (s[i] > '4')
{
k = 3; break;
}
}
if (k == 1 || k == 2)
{
s[pos]--;
for (int i = pos + 1; i < len; i++)
s[i] = '8';
}
else
{
s[pos]++;
for (int i = pos + 1; i < len; i++)
s[i] = '0';
}
}
}
int key = 0;
for (int i = 0; i < len; i++)
{
if (s[i] != '0')
{
key = 1; printf("%c", s[i]);
}
else
{
if(key==1)
printf("%c", s[i]);
}
}
if (key == 0)
cout << 0;
cout << endl;
}
return 0;
}

J.小Y写文章

K.树上最大值

L.K序列

（背包式滚动dp+模运算）

#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<algorithm>
using namespace std;
#define inf 0x3f3f3f3f
#define ll long long
const int maxn = 1e7 + 50;
int dp[2][maxn],a[maxn];
int main()
{
int n, mod, xx, ans = 0,cnt=0;
cin >> n >> mod;
for (int i = 0; i < n; i++)
{
scanf("%d", &xx);
if (xx%mod == 0)ans++;
else a[cnt++] = xx%mod;
}
int x = 0;
for (int i = 0; i < cnt; i++)
{
for (int j = 0; j < mod; j++)
if (j == 0 || dp[x][j])
dp[x ^ 1][(j + a[i]) % mod] = max(dp[x ^ 1][(j + a[i]) % mod], dp[x][j] + 1);
x ^= 1;
}
cout << ans + dp[x][0] << endl;
return 0;
}

• 广告
• 抄袭
• 版权
• 政治
• 色情
• 无意义
• 其他

120