题目
A Wasserstein Distance
最近对抗生成网络(GAN)很火,其中有一种变体WGAN,引入了一种新的距离来提高生成图片的质量。这个距离就是Wasserstein距离,又名铲土距离。 这个问题可以描述如下:
有两堆泥土,每一堆有n个位置,标号从1~n。第一堆泥土的第i个位置有ai克泥土,第二堆泥土的第i个位置有bi克泥土。小埃可以在第一堆泥土中任意移挪动泥土,具体地从第i个位置移动k克泥土到第j个位置,但是会消耗的体力。小埃的最终目的是通过在第一堆中挪动泥土,使得第一堆泥土最终的形态和第二堆相同,也就是ai=bi (1<=i<=n), 但是要求所花费的体力最小
左图为第一堆泥土的初始形态,右图为第二堆泥土的初始形态,颜色代表了一种可行的移动方案,使得第一堆泥土的形态变成第二堆泥土的形态
#include <bits/stdc++.h>
using namespace std;
int main() {
//freopen("inputlx.txt","r",stdin);
int t=0,n=0;
long long ans=0;
int a[100010],b[100010],c[100010];
scanf("%d",&t);
while(t--) {
scanf("%d",&n);
ans=0;
for(int i=1; i<=n; i++) {
scanf("%d",&a[i]);
}
for(int i=1; i<=n; i++) {
scanf("%d",&b[i]);
}
for(int i=1; i<=n; i++) {
c[i]=a[i]-b[i];
}
for(int i=1; i<=n-1; i++) {
if(c[i] > 0 && c[i] != 0) {
ans+=c[i];
c[i+1]+=c[i];
c[i] = 0;
}
if (c[i] < 0 && c[i] != 0) {
ans-=c[i];
c[i+1]+=c[i];
c[i]=0;
}
}
printf("%lld\n",ans);
}
return 0;
}
E 小Y吃苹果
小Y买了很多苹果,但他很贪吃,过了几天一下就吃剩一只了。每一天小Y会数出自己的苹果个数X,如果X是偶数,他就会吃掉只苹果;如果X是奇数,他就会吃掉只苹果。
你知道现在苹果只剩下一只,并且小Y是在N天前买的苹果,现在小Y想知道在那天买了多少苹果。当然,可能性不止一种,你只需要求出他买的苹果数量有多少种可能。
#include <bits/stdc++.h>
using namespace std;
int main(){
freopen("inputlx.txt", "r", stdin);
long long n=0,ans=0;
scanf("%lld",&n);
ans=pow(2,n);
printf("%lld",ans);
}
F 1 + 2 = 3?
小Y在研究数字的时候,发现了一个神奇的等式方程,他屈指算了一下有很多正整数x满足这个等式,比如1和2,现在问题来了,他想知道从小到大第N个满足这个等式的正整数,请你用程序帮他计算一下。 (表示按位异或运算)
#include <bits/stdc++.h>
using namespace std;
long long a[100],tot[100];
int main(){
memset(a, 0, sizeof(a));
memset(tot, 0, sizeof(tot));
a[1]=1;a[2]=1;a[3]=2;tot[1]=1;tot[2]=2;tot[3]=4;
for(int i=3;i<=99;i++){
a[i]=a[i-1]+a[i-2];
tot[i]=tot[i-1]+a[i];
}
// printf("a[99]%lld\n",a[60]);
freopen("inputlx.txt","r",stdin);
long long t,n,ans,temp,t1,j;
bitset<64> b;
scanf("%lld", &t);
while(t--){
b.reset();
scanf("%lld",&n);
for (int i = 1; i <= 99; i++)
{
if (tot[i]>=n&&tot[i-1]<n){
b.flip(i-1);
temp=i-1;
goto loop;
int x = max(1,2);
}
}
loop:
unsigned long long ans=b.to_ullong();
ans=ans+(n-temp-1);
printf("%lld\n",ans);
}
}
L K序数
给一个数组 a,长度为 n,若某个子序列中的和为 K 的倍数,那么这个序列被称为“K 序列”。现在要你 对数组 a 求出最长的子序列的长度,满足这个序列是 K 序列。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll p[100005];
int r(ll n, ll k)
{
int sum = 0;
for (ll i = 0; i < n; i++)
{
sum += p[i];
sum = sum % k;
}
if (sum % k == 0)
{
return n;
}
for (ll i = n - 1; i > 0; i--)
{
sum = 0;
for (ll ii = 0; ii < i; ii++)
{
sum += p[ii];
sum = sum % k;
}
if (sum % k == 0)
return i;
for (ll j = 0; j < n - i; j++)
{
sum = sum - p[j] + p[j + i];
sum = sum % k;
if (sum % k == 0)
return i;
}
}
return 0;
}
int main()
{
ll n, k;
//freopen("inputlx.txt","r",stdin);
while (cin >> n)
{
cin >> k;
memset(p, 0, sizeof(p));
for (ll i = 0; i < n; i++)
{
cin >> p[i];
}
cout << r(n, k) << endl;
}
return 0;
}
I 二数
我们把十进制下每一位都是偶数的数字叫做“二数”。 小埃表示自己很聪明,最近他不仅能够从小数到大:2,3,4,5….,也学会了从大数到小:100,99,98…,他想知道从一个数开始数最少的数就得到一个二数。但是聪明的小森已经偷偷在心里算好了小埃会数到哪个二数,请你求出他要数到哪个数吧。 换句话说,给定一个十进制下最多105位的数字,请你求出和这个数字的差的绝对值最小的二数,若答案不唯一,输出最小的那个。 也就是说,给定数字n,求出m,使得abs(n-m)最小且m[i] mod 2 = 0
#include <bits/stdc++.h>
using namespace std;
int main(){
int t;
char num[100010],ans[100010];
scanf("%d",&t);
while(t--){
memset(num, '\0', sizeof(num));
memset(ans, '\0', sizeof(ans));
scanf("%s",num);
int len=strlen(num);
if(len>=2){
if((num[len-1]-'0')%2!=0){
if((num[len-2]-'0')>=5)
num[len-1]=num[len-1]+'1';
for(int i=len-2;i<=0;i++){
num[]
}
}
}
if(len==1){
}
}
}