Problem B: Matrix Fast Power
题意:
Jelly has a sequence A, A1 = X, A2 = Y, when i ≥ 3, Ai = F(Ai−1)+F(Ai−2).
Where F(x) represents the sum of the digits of x. For example, F(283) = 2 + 8 + 3 = 13.Now, give you three integers X, Y and N, please calculate AN.
POINT:
很简单,找循环节。
可是训练赛中却写超时了。
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <string.h>
using namespace std;
#define LL long long
LL f(LL x)
{
LL sum=0;
while(x){
sum+=x%10;
x=x/10;
}
return sum;
}
void d(LL &x,LL &y)
{
LL t=x;
x=y;
y=f(t)+f(y);
}
LL mp[33][33];
LL flag[33][33];
void dfs(LL x,LL y,LL now)
{
if(mp[x][y]){
flag[x][y]=now-mp[x][y];
return;
}
mp[x][y]=now;
d(x,y);
dfs(x,y,now+1);
}
int main()
{
LL T;
scanf("%lld",&T);
LL cas=0;
while(T--){
LL x,y,n;
scanf("%lld %lld %lld",&x,&y,&n);
while(n>1&&(x>30||y>30)){
n--;
d(x,y);
}
memset(mp,0,sizeof mp);
dfs(x,y,0);
while(n>1&&flag[x][y]==0){
n--;
d(x,y);
}
n=n%(flag[x][y]);
if(!n) n=flag[x][y];
while(n>1){
n--;
d(x,y);
}
printf("Case #%lld: %lld\n",++cas,x);
}
return 0;
}
Problem C. Sometimes Naive
题意:
给你n个棒的长度,让你求出最多形成几个三角形
POINT:
用状压找出1的个数为3的倍数的答案。
然后dp更新就行了。
2.
最大团思路做,把3条边可以形成三角形的都找出来,作为一个点。
把点与点矛盾的连上一条边,这样问题就变成了求最大独立集。但是不是二分图。
所以取反图,求最大团。NP问题,随机算法跑,题目给你15秒。跑10000次稳过,其他看运气。
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <string.h>
using namespace std;
#define LL long long
const LL maxn =2048576;
LL dp[maxn];
LL a[22];
LL cnt;
LL three[maxn],cnt_three;
struct node
{
LL ans;
LL num;
bool friend operator < (node a,node b){
return a.num<b.num;
}
}ans[maxn];
LL check(LL x)
{
LL num[4];
LL c=0;
LL cn=0;
while(x){
c++;
if(x&1){
num[++cn]=a[c];
}
x>>=1;
}
if(num[1]+num[2]>num[3]&&num[3]+num[2]>num[1]&&num[1]+num[3]>num[2]){
return 1;
}
return 0;
}
void f(LL x)
{
LL b=x;
LL num=0;
while(x){
if(x&1) num++;
x>>=1;
}
if(num%3==0){
ans[++cnt].ans=b;
ans[cnt].num=num;
}
if(num==3){
if(check(b)){
three[++cnt_three]=b;
}
}
}
int main()
{
LL T;
scanf("%lld",&T);
LL cas=0;
while(T--){
LL n;
cnt_three=cnt=0;
scanf("%lld",&n);
memset(dp,0,sizeof dp);
for(LL i=1;i<=n;i++)
scanf("%lld",&a[i]);
for(LL i=0;i<(1<<n);i++){
f(i);
}
dp[0]=1;
sort(ans+1,ans+1+cnt);
for(LL i=1;i<=cnt;i++){
for(LL j=1;j<=cnt_three;j++){
if(dp[ans[i].ans]==1&&(ans[i].ans&three[j])==0){
dp[ans[i].ans|three[j]]=1;
}
}
}
for(LL i=cnt;i>=1;i--){
if(dp[ans[i].ans]){
printf("Case #%lld: %lld\n",++cas,ans[i].num/3);
break;
}
}
}
return 0;
}
2:
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <string.h>
#include <cstdlib>
#include <ctime>
using namespace std;
#define LL long long
const LL maxn = 2000+5;
LL a[22];
LL cnt;
LL check(LL x,LL y,LL z)
{
if(a[x]+a[y]>a[z]&&a[x]+a[z]>a[y]&&a[y]+a[z]>a[x]){
return (1<<x)|(1<<y)|(1<<z);
}
return -1;
}
LL dian[maxn];
LL mp[maxn][maxn];
LL b[maxn];
bool p[maxn];
void RANDOM()
{
srand(time(NULL));//换成0不行
for(LL i = 1;i <= cnt;i ++)
swap(b[i],b[rand()%cnt+1]);
return ;
}
LL JUDGE()
{
for(LL i = 1;i <= cnt;i ++)
p[i] = 0;
LL ans = 0;
for(LL i = 1;i <= cnt;i ++)
{
if(!p[i])
{
ans ++;
for(LL j = i+1;j <= cnt;j ++)
{
if(!mp[b[i]][b[j]])
p[j] = 1;
}
}
}
return ans;
}
int main()
{
// srand(time(NULL));
// cout<<rand();
LL T,n;
scanf("%lld",&T);
LL cas=0;
while(T--){
cnt=0;
scanf("%lld",&n);
for(LL i=1;i<=n;i++){
scanf("%lld",&a[i]);
}
for(LL i=1;i<=n;i++){
for(LL j=i+1;j<=n;j++){
for(LL k=j+1;k<=n;k++){
LL now=check(i,j,k);
if(now!=-1){
dian[++cnt]=now;
}
}
}
}
for(LL i=1;i<=cnt;i++){
for(LL j=1;j<=cnt;j++){
mp[i][j]=1;
if(dian[i]&dian[j]){
mp[i][j]=0;
}
}
}
for(LL i=1;i<=cnt;i++)
b[i]=i;
LL Max=0;
for(LL i=1;i<=10000;i++){
RANDOM();
if(Max==n/3) break;
Max=max(Max,JUDGE());
}
printf("Case #%lld: %lld\n",++cas,Max);
}
return 0;
}
Problem G: 最大公约数和最小公倍数问题
a*b=gcd*lcm.
个数就是1<<(lcm/gcd的【不同】质因数的个数的).
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <string.h>
using namespace std;
int num=0;
int flag[1000201];
void f(int x)
{
for(int i=2;i<=x;i++){
while(x%i==0){
if(flag[i]==0){
num++;
flag[i]=1;
}
x=x/i;
}
}
if(x!=1&&flag[x]==0)
num++;
}
int main()
{
int x,y;
scanf("%d %d",&x,&y);
if(x>y) swap(x, y);
int now=y/x;
if(now*x!=y){
printf("0\n");
return 0;
}
f(now);
int ans = 1;
for(int i=1;i<=num;i++){
ans=ans*2;
}
cout<<ans<<endl;
return 0;
}
总结:
被B题tle的头皮发麻,心态太脆弱了。
导致剩下3个小时处于神游状态!!
请给我反思一年!!