Problem A: 哦吼?GJC要防AK了?
思路:如果Y不是X的因数,因为X是自身的倍数,所以X是X的倍数而不是Y的倍数,反之,由于Y是X的因数,所以X的任何倍数都是Y的倍数;故该题只需判断X%Y;
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
long long x,y;cin >> x >> y;
if(x%y)
cout << x;
else
cout << "-1";
return 0;
}
Problem B: 730的天花板
思路:dp,设n时方案数为dp[n],则当n+1时,若第一列只有11方块,则方案数为dp[n-1],若第一第二行有22方块,则方案数为2dp[n-1],即得
**dp[n+1] = dp[n]+2dp[n-1]**;
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const ll mod = 19260817;
ll dp[10000005];
int main()
{
dp[0] = dp[1] = 1;dp[2] = 3;
for(int i = 3;i <= 10000000;++i)
dp[i] = (dp[i-1]+2*dp[i-2])%mod;
int T;cin >> T;
while(T--)
{
int n;cin >> n;
cout << dp[n] << endl;
}
return 0;
}
Problem C: gugugu
思路:模拟;
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
int a[100005];
int main()
{
a[1] = 1;
for(int i = 2;i <= sqrt(100005);++i)
{
if(!a[i])
for(int j = 2;i*j < 100005;++j)
a[i*j] = 1;
}
int n,sum = 0;cin >> n;
while(n--)
{
char s[105];cin >> s;
int len = strlen(s);
for(int i = 0;i < len-1;++i)
if(s[i]=='G'||s[i]=='g')
if(s[i+1]=='u'||s[i+1]=='U')
++sum;
}
if(a[sum])
cout << "gu";
else
cout << "gugugu";
return 0;
}
Problem D: 不可思议唤来不可思议β
思路:排列组合题,假设有333457789这九个数,假设每个数字不同则有A(9,9)种排列,因为3与7存在重复运算=>A(3,3),A(2,2),则真正的排列数为A(9,9)/A(3,3)/A(2,2);在此基础上,拿出其中数字3,则余下数字的排列数就是3在某一位的出现次数,该排列数为A(8,8)/A(2,2)/A(2,2),以此类推,求出一个位上所有数字的重复次数与其乘积之和,即可算得答案;
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
ll A[15];
int main()
{
A[0] = A[1] = 1;
for(int i = 2; i <= 10;++i)
A[i] = A[i-1]*i;
int n;
while(scanf("%d",&n)&&n)
{
ll a[15] = {0};
for(int i = 0;i < n;++i)
{
int tt;
cin >> tt;
a[tt]++;
}
ll sum = 0;
for(int i = 1;i <= 9;++i)
{
if(!a[i])
continue;
ll pos = i*A[n-1];
for(int j = 0;j < 10;++j)
{
if(a[j])
{
if(j == i)
pos /= A[a[j]-1];
else
pos /= A[a[j]];
}
}
sum += pos;
}
ll ans = 0;
for(int i = 1;i <= n;++i)
ans = ans*10+sum;
printf("%lld\n",ans);
}
return 0;
}
Problem E: Hacking to the Gate
思路:看不懂数学符号,看样例盲猜等于1,发现wa了又盲猜n,对了
Problem F: 维生素
思路:一开始我是用位运算+dp的,后来发现算法有问题,在某大佬指导下用了贪心算法,具体贪心方法如下;
abc可以由abc,a+bc,ab+c,ac+b,a+b+c,三种方法得到,先记录含a的饮料,再记录含b的饮料,因此类推,设v[a]为含a饮料价格的最小值,则答案为v[abc],v[a]+v[bc],v[b]+v[ac],v[c]+v[ab],v[a]+v[b]+v[c]中的最小值;
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
const ll maxn = 1e8;
int a[10];
int main()
{
int T;cin >> T;
while(T--)
{
int n;cin >> n;
for(int i = 0;i < 8;++i)
a[i] = maxn;
for(int i = 0;i < n;++i)
{
char t[8];int p;
cin >> p;scanf("%[^\n]",t);
int len = strlen(t),tt = 0;
for(int j = 0;j < len;++j)
{
if(t[j] == 'A')//用位代替维生素;
tt += 4;
else if(t[j] == 'B')
tt += 2;
else if(t[j] == 'C')
tt += 1;
}
if(tt==1&&p < a[1])
a[1] = p;
else if(tt==2&&p<a[2])
a[2] = p;
else if(tt==3)
{
if(p < a[1])
a[1] = p;
if(p < a[2])
a[2] = p;
if(p < a[3])
a[3] = p;
}
else if(tt==4&&p<a[4])
a[4] = p;
else if(tt==5)
{
if(p < a[4])
a[4] = p;
if(p < a[1])
a[1] = p;
if(p < a[5])
a[5] = p;
}
else if(tt==6)
{
if(p < a[4])
a[4] = p;
if(p < a[2])
a[2] = p;
if(p < a[6])
a[6] = p;
}
else if(tt==7)
{
if(p < a[1])
a[1] = p;
if(p < a[2])
a[2] = p;
if(p < a[3])
a[3] = p;
if(p < a[4])
a[4] = p;
if(p < a[5])
a[5] = p;
if(p < a[6])
a[6] = p;
if(p < a[7])
a[7] = p;
}
}
int ans = min(a[1]+a[2]+a[4],a[6]+a[1]);
ans = min(ans,a[5]+a[2]);
ans = min(ans,a[4]+a[3]);
ans = min(ans,a[7]);
if(ans < maxn)
cout << ans << endl;
else
cout << "-1" << endl;
}
return 0;
}
Problem G: 你选择的这个世界
思路:首先,如果硬币最终为正面,则其被翻奇数次,一个硬币被翻的次数等于其因数的个数,则要求正面的硬币因数个数为奇数,现拿4举例,4的因数有1,2,4,而6的因数为1,2,3,6,易发现当编号为平方数时因数个数为奇数个,因为若m = a*b,则a,b分别为m的因数或ab,两者为m的同一个因数,若ab则m为平方数,若m不为平方数,则易知因数成对存在,有偶数个;
#include<cmath>
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
int main()
{
int T;cin >> T;
while(T--)
{
ll n;cin >> n;
for(ll i = 1;i <= sqrt(n);++i)
{
if(i+1 <= sqrt(n))
cout << i*i << ' ';
else
cout << i*i;
}
cout << endl;
}
return 0;
}
Problem H: 邱总的游戏
思路:其实这道题我是看题解的,博弈的必胜态实在找不到
题解链接;
Problem I: 二律的日常
思路:这题还是用贪心,首先是按顺序看的,前面的能买就买,而当价格为0时就是必买,设价格为0的物品有m件,则当m > k时不可能只买k件,当 n == k时可以带无限多的钱,排除这两种情况,从余下价格不为0的物品中按顺序选m-k件4并加上挑选后余下物品最低价减1的钱数即为最多带的钱;
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
ll a[100005];
int main()
{
int T;cin >> T;
while(T--)
{
int n,k;cin >> n >> k;
for(int i = 0;i < n;++i)
scanf("%lld",a+i);
int ans;
if(k == n)
ans = -2;
else
{
int tail = 0;
while(tail < k)
ans += a[tail++];
sort(a+k,a+n);
int i ;
for(i = k;i < n&&tail;++i)
if(a[i] == 0)
ans -= a[--tail];
if(!tail&&!a[i])
ans = -1;
else
{
sort(a+tail,a+n);
ans += a[tail]-1;
}
}
if(ans == -1)
cout << "alsnb" << endl;
if(ans == -2)
cout << "ksfnb" << endl;
if(ans >= 0)
cout << ans << endl;
}
return 0;
}